diff --git a/.changeset/many-tomatoes-arrive.md b/.changeset/many-tomatoes-arrive.md new file mode 100644 index 000000000..2f7151a41 --- /dev/null +++ b/.changeset/many-tomatoes-arrive.md @@ -0,0 +1,5 @@ +--- +"@hyperdx/app": patch +--- + +fix: Prevent crashes on Services and ClickHouse dashboards diff --git a/packages/app/src/ClickhousePage.tsx b/packages/app/src/ClickhousePage.tsx index 91664af75..53c1add13 100644 --- a/packages/app/src/ClickhousePage.tsx +++ b/packages/app/src/ClickhousePage.tsx @@ -12,7 +12,6 @@ import { format as formatSql } from '@hyperdx/common-utils/dist/sqlFormatter'; import { DisplayType } from '@hyperdx/common-utils/dist/types'; import { Box, - BoxComponentProps, Button, Flex, Grid, @@ -38,6 +37,7 @@ import OnboardingModal from './components/OnboardingModal'; import { useDashboardRefresh } from './hooks/useDashboardRefresh'; import { useConnections } from './connection'; import { parseTimeQuery, useNewTimeQuery } from './timeQuery'; +import { usePrevious } from './utils'; // TODO: This is a hack to set the default time range const defaultTimeRange = parseTimeQuery('Past 1h', false) as [Date, Date]; @@ -443,12 +443,13 @@ function ClickhousePage() { }); const watchedConnection = useWatch({ control, name: 'connection' }); + const previousWatchedConnection = usePrevious(watchedConnection); useEffect(() => { - if (watchedConnection !== connection) { + if (previousWatchedConnection !== watchedConnection) { setConnection(watchedConnection ?? null); } - }, [watchedConnection, connection, setConnection]); + }, [watchedConnection, setConnection, previousWatchedConnection]); const DEFAULT_INTERVAL = 'Past 1h'; const [displayedTimeInputValue, setDisplayedTimeInputValue] = useState(DEFAULT_INTERVAL); diff --git a/packages/app/src/ServicesDashboardPage.tsx b/packages/app/src/ServicesDashboardPage.tsx index 3169e4b2f..bc20fadb2 100644 --- a/packages/app/src/ServicesDashboardPage.tsx +++ b/packages/app/src/ServicesDashboardPage.tsx @@ -75,6 +75,7 @@ import { IS_LOCAL_MODE } from './config'; import DashboardFilters from './DashboardFilters'; import DashboardFiltersModal from './DashboardFiltersModal'; import { HARD_LINES_LIMIT } from './HDXMultiSeriesTimeChart'; +import { usePrevious } from './utils'; type AppliedConfigParams = { source?: string | null; @@ -1431,7 +1432,11 @@ function ServicesDashboardPage() { }); const service = useWatch({ control, name: 'service' }); + const previousService = usePrevious(service); + const sourceId = useWatch({ control, name: 'source' }); + const previousSourceId = usePrevious(sourceId); + const { data: source } = useSource({ id: sourceId, }); @@ -1500,18 +1505,22 @@ function ServicesDashboardPage() { }, [handleSubmit, setAppliedConfigParams, onSearch, displayedTimeInputValue]); // Auto-submit when source changes + // Note: do not include appliedConfig.source in the deps, + // to avoid infinite render loops when navigating away from the page useEffect(() => { - if (sourceId && sourceId !== appliedConfig.source) { + if (sourceId && sourceId != previousSourceId) { onSubmit(); } - }, [sourceId, appliedConfig.source, onSubmit]); + }, [sourceId, onSubmit, previousSourceId]); // Auto-submit when service changes + // Note: do not include appliedConfig.service in the deps, + // to avoid infinite render loops when navigating away from the page useEffect(() => { - if (service !== appliedConfig.service) { + if (service != previousService) { onSubmit(); } - }, [service, appliedConfig.service, onSubmit]); + }, [service, onSubmit, previousService]); return (