Skip to content

Commit

Permalink
Added reuseItemsOnTableResize param (#1858)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmingles committed Mar 19, 2024
1 parent 0c5980e commit c8781da
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 13 deletions.
69 changes: 57 additions & 12 deletions packages/jsapi-components/src/useInitializeViewportData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,50 @@ import useTableSize from './useTableSize';

const log = Log.module('useInitializeViewportData');

/**
* Given an array of items, returns a new array containing the target number of
* items. If reuseExistingItems is true, existing items will be re-used. If
* false, all items will be replaced with new, empty items.
* @param items The array of items to resize.
* @param targetSize The desired size of the array.
* @param reuseExistingItems If true, existing items will be re-used. If false,
* all items will be replaced with new, empty items.
* @returns The resized array of items.
*/
function resizeItemsArray<T>({
items,
targetSize,
reuseExistingItems,
}: {
items: KeyedItem<T, string>[];
reuseExistingItems: boolean;
targetSize: number;
}): KeyedItem<T, string>[] {
const currentSize = items.length;

// If size isn't changing, do nothing
if (currentSize === targetSize) {
return items;
}

log.debug('size changed:', { currentSize, targetSize });

if (!reuseExistingItems) {
// All items will be replaced with new data. This is preferred in certain
// scenarios to avoid the user seeing items shift around multiple times
// while data is being loaded.
return Array.from(generateEmptyKeyedItems<T>(0, targetSize - 1));
}

// Drop extra items
if (currentSize > targetSize) {
return items.slice(0, targetSize - 1);
}

// Add missing items
return [...items, ...generateEmptyKeyedItems<T>(currentSize, targetSize - 1)];
}

/**
* Initializes a ListData instance that can be used for windowed views of a
* Table. The list must always contain a KeyedItem for every record in the table,
Expand All @@ -18,28 +62,29 @@ const log = Log.module('useInitializeViewportData');
* source table. This is intended for "human" sized tables such as those used in
* admin panels. This is not suitable for "machine" scale with millions+ rows.
* @param table The table that will be used to determine the list size.
* @param reuseItemsOnTableResize If true, the items will be reused when the
* table resizes. Defaults to false which will replace the items when the table
* resizes.
* @returns a WindowedListData object.
*/
export function useInitializeViewportData<T>(
table: dh.Table | dh.TreeTable | null
table: dh.Table | dh.TreeTable | null,
reuseItemsOnTableResize = false
): WindowedListData<KeyedItem<T>> {
const viewportData = useWindowedListData<KeyedItem<T>>({});

// If the table changes size, we need to re-initialize it.
const targetSize = Math.max(0, useTableSize(table));

// Whenever the table reference or size changes, replace the list with empty
// items. This is preferred over updating items in place to avoid the user
// seeing items shift around multiple times.
// Whenever the table reference or size changes, resize the list.
useEffect(() => {
const currentSize = viewportData.items.length;

if (targetSize !== currentSize) {
log.debug('size changed:', { currentSize, targetSize });
viewportData.setItems(
Array.from(generateEmptyKeyedItems<T>(0, targetSize - 1))
);
}
viewportData.setItems(
resizeItemsArray({
items: viewportData.items,
targetSize,
reuseExistingItems: reuseItemsOnTableResize,
})
);

// Intentionally excluding viewportData since it changes on every render.
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
9 changes: 8 additions & 1 deletion packages/jsapi-components/src/useViewportData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface UseViewportDataProps<
TItem,
TTable extends dh.Table | dh.TreeTable,
> {
reuseItemsOnTableResize?: boolean;
table: TTable | null;
itemHeight?: number;
scrollDebounce?: number;
Expand Down Expand Up @@ -64,6 +65,8 @@ export interface UseViewportDataResult<
* @param viewportSize The number of items to display in the viewport.
* @param viewportPadding The number of items to fetch at start and end of the viewport.
* @param deserializeRow A function to deserialize a row from the Table.
* @param reuseItemsOnTableResize If true, existing items will be re-used when
* the table size changes.
* @returns An object for managing Table viewport state.
*/
export function useViewportData<TItem, TTable extends dh.Table | dh.TreeTable>({
Expand All @@ -73,8 +76,12 @@ export function useViewportData<TItem, TTable extends dh.Table | dh.TreeTable>({
viewportSize = 10,
viewportPadding = 50,
deserializeRow = defaultRowDeserializer,
reuseItemsOnTableResize = false,
}: UseViewportDataProps<TItem, TTable>): UseViewportDataResult<TItem, TTable> {
const viewportData = useInitializeViewportData<TItem>(table);
const viewportData = useInitializeViewportData<TItem>(
table,
reuseItemsOnTableResize
);

const setPaddedViewport = useSetPaddedViewportCallback(
table,
Expand Down

0 comments on commit c8781da

Please sign in to comment.