diff --git a/ui/src/pages/Dashboard/DashboardPage.tsx b/ui/src/pages/Dashboard/DashboardPage.tsx index 3a444c9d2f..b76652903e 100644 --- a/ui/src/pages/Dashboard/DashboardPage.tsx +++ b/ui/src/pages/Dashboard/DashboardPage.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import WaitSpinner from '@splunk/react-ui/WaitSpinner'; import TabLayout from '@splunk/react-ui/TabLayout'; import ErrorBoundary from '../../components/ErrorBoundary/ErrorBoundary'; @@ -14,13 +14,20 @@ import { getUnifiedConfigs } from '../../util/util'; /** * * @param {string} fileName name of json file in custom dir + * @param {boolean} isComponentMounted used to remove component data leakage, determines if component is still mounted and dataHandler referes to setState * @param {string} setData callback, called with data as params */ -function loadJson(fileName: string, dataHandler: (data: Record) => void) { +function loadJson( + fileName: string, + isComponentMounted: boolean, + dataHandler: (data: Record) => void +) { fetch(/* webpackIgnore: true */ `${getBuildDirPath()}/custom/${fileName}`) .then((res) => res.json()) .then((external) => { - dataHandler(external); + if (isComponentMounted) { + dataHandler(external); + } }) .catch((e) => { // eslint-disable-next-line no-console @@ -34,22 +41,40 @@ function DashboardPage() { const [errorDef, setErrorDef] = useState | null>(null); const [resourceDef, setResourceDef] = useState | null>(null); const [customDef, setCustomDef] = useState | null>(null); + const isComponentMounted = useRef(true); useEffect(() => { - loadJson('panels_to_display.json', (data: { default?: boolean; custom?: boolean }) => { - if (data?.default) { - loadJson('overview_definition.json', setOverviewDef); - loadJson('data_ingestion_tab_definition.json', setDataIngestionDef); - loadJson('errors_tab_definition.json', setErrorDef); - loadJson('resources_tab_definition.json', setResourceDef); - } - if (data?.custom) { - loadJson('custom.json', setCustomDef); + loadJson( + 'panels_to_display.json', + isComponentMounted.current, + (data: { default?: boolean; custom?: boolean }) => { + if (data?.default) { + loadJson( + 'overview_definition.json', + isComponentMounted.current, + setOverviewDef + ); + loadJson( + 'data_ingestion_tab_definition.json', + isComponentMounted.current, + setDataIngestionDef + ); + loadJson('errors_tab_definition.json', isComponentMounted.current, setErrorDef); + loadJson( + 'resources_tab_definition.json', + isComponentMounted.current, + setResourceDef + ); + } + if (data?.custom) { + loadJson('custom.json', isComponentMounted.current, setCustomDef); + } } - }); + ); document.body.classList.add('grey_background'); return () => { + isComponentMounted.current = false; document.body.classList.remove('grey_background'); }; }, []); diff --git a/ui/src/pages/Dashboard/tests/DashBoardPage.test.tsx b/ui/src/pages/Dashboard/tests/DashBoardPage.test.tsx index 66301e3a41..5bb5701bf0 100644 --- a/ui/src/pages/Dashboard/tests/DashBoardPage.test.tsx +++ b/ui/src/pages/Dashboard/tests/DashBoardPage.test.tsx @@ -6,9 +6,14 @@ import DashboardPage from '../DashboardPage'; import { server } from '../../../mocks/server'; import { DASHBOARD_JSON_MOCKS } from './mockJs'; +import { getGlobalConfigMock } from '../../../mocks/globalConfigMock'; +import { setUnifiedConfig } from '../../../util/util'; +import { consoleError } from '../../../../jest.setup'; it('dashboard page renders waiting spinner', async () => { server.use(http.get('/custom/panels_to_display.json', () => HttpResponse.json({}))); + const mockConfig = getGlobalConfigMock(); + setUnifiedConfig(mockConfig); render(); @@ -17,8 +22,13 @@ it('dashboard page renders waiting spinner', async () => { }); it('render with all default dashboards', async () => { + consoleError.mockImplementation(() => {}); DASHBOARD_JSON_MOCKS.forEach((mock: RequestHandler) => server.use(mock)); + + const mockConfig = getGlobalConfigMock(); + setUnifiedConfig(mockConfig); render(); + const timeLabels = await screen.findAllByText('Time'); expect(timeLabels[0]).toBeInTheDocument(); expect(timeLabels.length).toEqual(2); diff --git a/ui/src/pages/Dashboard/tests/mockJs.ts b/ui/src/pages/Dashboard/tests/mockJs.ts index 7ea6ab4781..ce66a583ce 100644 --- a/ui/src/pages/Dashboard/tests/mockJs.ts +++ b/ui/src/pages/Dashboard/tests/mockJs.ts @@ -18,6 +18,9 @@ export const DASHBOARD_JSON_MOCKS = [ http.get('/custom/errors_tab_definition.json', () => HttpResponse.json(MOCK_ERROR_TAB_DEFINITION) ), + http.get('/custom/resources_tab_definition.json', () => + HttpResponse.json(MOCK_ERROR_TAB_DEFINITION) + ), http.post('/services/search/jobs', () => HttpResponse.error()), http.get('/services/authentication/current-context', () => HttpResponse.error()), ];