Skip to content

Commit 4889205

Browse files
authored
fix: Prevent crashes on Services and ClickHouse dashboards (#1535)
Closes HDX-3125 Closes HDX-3126 # Summary This PR fixes two application crashes due to infinite render loops: `useQueryState value updates --> set form values --> trigger form's useWatch/watch --> triggers useEffect --> calls setQueryState --> repeat...`. In these cases, the fix is to compare useWatch values to the previous useWatch value (using usePrevious) and only call setQueryState when the form value has changed. Before, the useEffect was also called when the query state changes.
1 parent 103c63c commit 4889205

File tree

3 files changed

+22
-7
lines changed

3 files changed

+22
-7
lines changed

.changeset/many-tomatoes-arrive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": patch
3+
---
4+
5+
fix: Prevent crashes on Services and ClickHouse dashboards

packages/app/src/ClickhousePage.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { format as formatSql } from '@hyperdx/common-utils/dist/sqlFormatter';
1212
import { DisplayType } from '@hyperdx/common-utils/dist/types';
1313
import {
1414
Box,
15-
BoxComponentProps,
1615
Button,
1716
Flex,
1817
Grid,
@@ -38,6 +37,7 @@ import OnboardingModal from './components/OnboardingModal';
3837
import { useDashboardRefresh } from './hooks/useDashboardRefresh';
3938
import { useConnections } from './connection';
4039
import { parseTimeQuery, useNewTimeQuery } from './timeQuery';
40+
import { usePrevious } from './utils';
4141

4242
// TODO: This is a hack to set the default time range
4343
const defaultTimeRange = parseTimeQuery('Past 1h', false) as [Date, Date];
@@ -443,12 +443,13 @@ function ClickhousePage() {
443443
});
444444

445445
const watchedConnection = useWatch({ control, name: 'connection' });
446+
const previousWatchedConnection = usePrevious(watchedConnection);
446447

447448
useEffect(() => {
448-
if (watchedConnection !== connection) {
449+
if (previousWatchedConnection !== watchedConnection) {
449450
setConnection(watchedConnection ?? null);
450451
}
451-
}, [watchedConnection, connection, setConnection]);
452+
}, [watchedConnection, setConnection, previousWatchedConnection]);
452453
const DEFAULT_INTERVAL = 'Past 1h';
453454
const [displayedTimeInputValue, setDisplayedTimeInputValue] =
454455
useState(DEFAULT_INTERVAL);

packages/app/src/ServicesDashboardPage.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import { IS_LOCAL_MODE } from './config';
7575
import DashboardFilters from './DashboardFilters';
7676
import DashboardFiltersModal from './DashboardFiltersModal';
7777
import { HARD_LINES_LIMIT } from './HDXMultiSeriesTimeChart';
78+
import { usePrevious } from './utils';
7879

7980
type AppliedConfigParams = {
8081
source?: string | null;
@@ -1431,7 +1432,11 @@ function ServicesDashboardPage() {
14311432
});
14321433

14331434
const service = useWatch({ control, name: 'service' });
1435+
const previousService = usePrevious(service);
1436+
14341437
const sourceId = useWatch({ control, name: 'source' });
1438+
const previousSourceId = usePrevious(sourceId);
1439+
14351440
const { data: source } = useSource({
14361441
id: sourceId,
14371442
});
@@ -1500,18 +1505,22 @@ function ServicesDashboardPage() {
15001505
}, [handleSubmit, setAppliedConfigParams, onSearch, displayedTimeInputValue]);
15011506

15021507
// Auto-submit when source changes
1508+
// Note: do not include appliedConfig.source in the deps,
1509+
// to avoid infinite render loops when navigating away from the page
15031510
useEffect(() => {
1504-
if (sourceId && sourceId !== appliedConfig.source) {
1511+
if (sourceId && sourceId != previousSourceId) {
15051512
onSubmit();
15061513
}
1507-
}, [sourceId, appliedConfig.source, onSubmit]);
1514+
}, [sourceId, onSubmit, previousSourceId]);
15081515

15091516
// Auto-submit when service changes
1517+
// Note: do not include appliedConfig.service in the deps,
1518+
// to avoid infinite render loops when navigating away from the page
15101519
useEffect(() => {
1511-
if (service !== appliedConfig.service) {
1520+
if (service != previousService) {
15121521
onSubmit();
15131522
}
1514-
}, [service, appliedConfig.service, onSubmit]);
1523+
}, [service, onSubmit, previousService]);
15151524

15161525
return (
15171526
<Box p="sm">

0 commit comments

Comments
 (0)