Skip to content

Commit be82b14

Browse files
authored
fix: DH-14630: useDebouncedViewportSearch: memoization bug (#1273)
Supports DH-14630 fixes #1272
1 parent 588cb8f commit be82b14

3 files changed

Lines changed: 20 additions & 7 deletions

File tree

packages/jsapi-components/src/useDebouncedViewportSearch.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import debounce from 'lodash.debounce';
22
import type { Table, TreeTable } from '@deephaven/jsapi-types';
33
import { TableUtils } from '@deephaven/jsapi-utils';
44
import { useApi } from '@deephaven/jsapi-bootstrap';
5+
import Log from '@deephaven/log';
56
import { useEffect, useMemo } from 'react';
67
import { UseViewportDataResult } from './useViewportData';
78

9+
const log = Log.module('useDebouncedViewportSearch');
10+
811
export const DEBOUNCE_VIEWPORT_SEARCH_MS = 200;
912

1013
/**
@@ -13,6 +16,7 @@ export const DEBOUNCE_VIEWPORT_SEARCH_MS = 200;
1316
* @param viewportData Table viewport to filter
1417
* @param columnName Column name to filter by
1518
* @param debounceMs Millisecond value to debounce
19+
* @returns A debounced search function
1620
*/
1721
export default function useDebouncedViewportSearch<
1822
I,
@@ -24,34 +28,39 @@ export default function useDebouncedViewportSearch<
2428
): (searchText: string) => void {
2529
const dh = useApi();
2630
const tableUtils = useMemo(() => new TableUtils(dh), [dh]);
31+
const { table, applyFiltersAndRefresh } = viewportData;
32+
2733
const debouncedSearch = useMemo(
2834
() =>
2935
debounce((searchText: string) => {
30-
if (viewportData.table == null) {
36+
log.debug(`Applying debounced searchText '${searchText}'`);
37+
38+
if (table == null) {
3139
return;
3240
}
3341

3442
const searchTextTrimmed = searchText.trim();
3543

3644
if (searchTextTrimmed === '') {
37-
viewportData.applyFiltersAndRefresh([]);
45+
applyFiltersAndRefresh([]);
3846
return;
3947
}
4048

41-
const column = viewportData.table.findColumn(columnName);
49+
const column = table.findColumn(columnName);
4250
const value = tableUtils.makeFilterValue(
4351
column.type,
4452
searchTextTrimmed
4553
);
4654
const filter = [column.filter().contains(value)];
4755

48-
viewportData.applyFiltersAndRefresh(filter);
56+
applyFiltersAndRefresh(filter);
4957
}, debounceMs),
50-
[columnName, debounceMs, tableUtils, viewportData]
58+
[applyFiltersAndRefresh, columnName, debounceMs, table, tableUtils]
5159
);
5260

5361
useEffect(
5462
() => () => {
63+
log.debug('Cancelling debounced search function');
5564
debouncedSearch.cancel();
5665
},
5766
[debouncedSearch]

packages/jsapi-components/src/useInitializeViewportData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import useTableSize from './useTableSize';
1515
* source table. This is intended for "human" sized tables such as those used in
1616
* admin panels. This is not suitable for "machine" scale with millions+ rows.
1717
* @param table The table that will be used to determine the list size.
18-
* @returns
18+
* @returns a React Stately ListData object. Note that this object is recreated
19+
* by React Stately on every render.
1920
*/
2021
export default function useInitializeViewportData<T>(
2122
table: Table | TreeTable | null

packages/jsapi-components/src/useViewportData.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ export interface UseViewportDataResult<
4747
* @param table
4848
* @param viewportSize
4949
* @param viewportPadding
50-
* @returns An object for managing Table viewport state.
50+
* @returns An object for managing Table viewport state. Note that the returned
51+
* object changes on every render due to the `viewportData` not being memoized.
52+
* This is due to the underlying React Stately `useListData` implementation that
53+
* also changes its returned object on every render.
5154
*/
5255
export default function useViewportData<
5356
TItem,

0 commit comments

Comments
 (0)