Skip to content

Commit bfaa036

Browse files
committed
Merge branch 'feat/sort-columns' into alpha
2 parents 933e560 + 0965d90 commit bfaa036

File tree

4 files changed

+53
-23
lines changed

4 files changed

+53
-23
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"dependencies": {
3737
"ag-grid-community": "^31.2.1",
3838
"ag-grid-react": "^31.2.1",
39+
"dequal": "^2.0.3",
3940
"lodash.debounce": "^4.0.8",
4041
"react": "18.2.0",
4142
"react-dom": "18.2.0",

src/components/InfiniteTable/InfiniteTable.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ import { TableProps } from "@/types";
2525
import { useDeepArrayMemo } from "@/hooks/useDeepArrayMemo";
2626
import { HeaderCheckbox } from "./HeaderCheckbox";
2727
import { useRowSelection } from "./useRowSelection";
28-
import { useColumnState } from "./useColumnState";
28+
import { areStatesEqual, useColumnState } from "./useColumnState";
2929
import { CHECKBOX_COLUMN, STATUS_COLUMN } from "./columnStateHelper";
3030

3131
const DEBOUNCE_TIME = 50;
32+
const DEFAULT_TOTAL_ROWS_VALUE = Number.MAX_SAFE_INTEGER;
3233

3334
export type InfiniteTableProps = Omit<
3435
TableProps,
@@ -42,14 +43,14 @@ export type InfiniteTableProps = Omit<
4243
startRow: number;
4344
endRow: number;
4445
sortFields?: Record<string, SortDirection>;
45-
}) => Promise<any[]>;
46+
}) => Promise<any[] | undefined>;
4647
height?: number;
4748
onColumnChanged?: (columnsState: ColumnState[]) => void;
4849
onGetColumnsState?: () => ColumnState[] | undefined;
4950
onGetFirstVisibleRowIndex?: () => number | undefined;
5051
onChangeFirstVisibleRowIndex?: (index: number) => void;
5152
onGetSelectedRowKeys?: () => any[] | undefined;
52-
totalRows: number;
53+
totalRows?: number;
5354
allRowSelectedMode?: boolean;
5455
onAllRowSelectedModeChange?: (allRowSelectedMode: boolean) => void;
5556
footer?: React.ReactNode;
@@ -78,7 +79,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
7879
onChangeFirstVisibleRowIndex,
7980
onGetFirstVisibleRowIndex,
8081
onGetSelectedRowKeys,
81-
totalRows,
82+
totalRows = DEFAULT_TOTAL_ROWS_VALUE,
8283
onAllRowSelectedModeChange,
8384
allRowSelectedMode: allRowSelectedModeProps,
8485
footer,
@@ -92,7 +93,6 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
9293
const firstTimeOnBodyScroll = useRef(true);
9394
const allRowSelectedModeRef = useRef<boolean>(false);
9495
const containerRef = useRef<HTMLDivElement>(null);
95-
const columnChangeListenerReady = useRef(false);
9696
const totalHeight = footer ? heightProps + footerHeight : heightProps;
9797
const tableHeight = footer ? heightProps - footerHeight : heightProps;
9898

@@ -128,7 +128,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
128128
const columns = useDeepArrayMemo(columnsProps, "key");
129129

130130
const {
131-
applyColumnState,
131+
loadPersistedColumnState,
132132
columnsPersistedStateRef,
133133
applyAndUpdateNewState,
134134
} = useColumnState({
@@ -141,16 +141,19 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
141141

142142
const onColumnChanged = useCallback(() => {
143143
const state = gridRef?.current?.api.getColumnState();
144-
if (!columnChangeListenerReady.current) {
145-
columnChangeListenerReady.current = true;
144+
if (!state) {
146145
return;
147146
}
148-
if (!state) {
147+
if (areStatesEqual(state, columnsPersistedStateRef.current)) {
149148
return;
150149
}
151150
applyAndUpdateNewState(state);
152151
onColumnsChangedProps?.(state);
153-
}, [applyAndUpdateNewState, onColumnsChangedProps]);
152+
}, [
153+
applyAndUpdateNewState,
154+
columnsPersistedStateRef,
155+
onColumnsChangedProps,
156+
]);
154157

155158
const onColumnMoved = useCallback(() => {
156159
onColumnChanged();
@@ -166,10 +169,6 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
166169
[onColumnChanged],
167170
);
168171

169-
const onSortChanged = useCallback(() => {
170-
gridRef.current?.api?.purgeInfiniteCache();
171-
}, []);
172-
173172
const getSortedFields = useCallback(():
174173
| Record<string, SortDirection>
175174
| undefined => {
@@ -217,7 +216,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
217216
const storedState = columnsPersistedStateRef.current;
218217
const storedStateKeys = storedState?.map((col: any) => col.colId);
219218

220-
const restOfColumns = columns.map((column) => ({
219+
const restOfColumns: ColDef[] = columns.map((column) => ({
221220
field: column.key,
222221
sortable: column.isSortable,
223222
headerName: column.title,
@@ -228,6 +227,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
228227

229228
// restOfColumns should be sorted by the order of the storedState
230229
storedState &&
230+
storedStateKeys &&
231231
restOfColumns.sort((a, b) => {
232232
const aIndex = storedStateKeys.indexOf(a.field);
233233
const bIndex = storedStateKeys.indexOf(b.field);
@@ -274,6 +274,10 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
274274
endRow,
275275
sortFields: getSortedFields(),
276276
});
277+
if (!data) {
278+
params.failCallback();
279+
return;
280+
}
277281
let lastRow = -1;
278282
if (data.length < endRow - startRow) {
279283
lastRow = startRow + data.length;
@@ -317,10 +321,8 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
317321
}
318322
}
319323
gridRef.current?.api.hideOverlay();
320-
applyColumnState();
321324
},
322325
[
323-
applyColumnState,
324326
getSortedFields,
325327
hasStatusColumn,
326328
onGetSelectedRowKeys,
@@ -333,11 +335,12 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
333335

334336
const onGridReady = useCallback(
335337
(params: GridReadyEvent) => {
338+
loadPersistedColumnState();
336339
params.api.setGridOption("datasource", {
337340
getRows,
338341
});
339342
},
340-
[getRows],
343+
[getRows, loadPersistedColumnState],
341344
);
342345

343346
const onRowDoubleClicked = useCallback(
@@ -397,7 +400,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
397400
onDragStopped={onColumnMoved}
398401
onColumnResized={onColumnResized}
399402
rowModelType={"infinite"}
400-
cacheBlockSize={20}
403+
cacheBlockSize={200}
401404
onSelectionChanged={onSelectionChangedDebounced}
402405
cacheOverflowSize={2}
403406
maxConcurrentDatasourceRequests={1}
@@ -408,7 +411,7 @@ const InfiniteTableComp = forwardRef<InfiniteTableRef, InfiniteTableProps>(
408411
onBodyScroll={onBodyScroll}
409412
blockLoadDebounceMillis={DEBOUNCE_TIME}
410413
suppressDragLeaveHidesColumns={true}
411-
onSortChanged={onSortChanged}
414+
onSortChanged={onColumnChanged}
412415
/>
413416
</div>
414417
{footer && <div style={{ height: footerHeight }}>{footer}</div>}

src/components/InfiniteTable/useColumnState.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from "./columnStateHelper";
99
import { TableColumn } from "@/types";
1010
import { useDeepCompareCallback } from "use-deep-compare";
11+
import { dequal } from "dequal";
1112

1213
const DEBOUNCE_DELAY = 50;
1314

@@ -25,7 +26,7 @@ export const useColumnState = ({
2526
onGetColumnsState?: () => ColumnState[] | undefined;
2627
}) => {
2728
const firstTimeResized = useRef(false);
28-
const columnsPersistedStateRef = useRef<any>();
29+
const columnsPersistedStateRef = useRef<ColumnState[]>();
2930

3031
const columnsToIgnore = FIXED_COLUMNS_TO_IGNORE;
3132
if (hasStatusColumn) {
@@ -92,7 +93,7 @@ export const useColumnState = ({
9293
});
9394
}, [columnsToIgnore, gridRef, remainingBlankSpace, runDeferredCallback]);
9495

95-
const applyColumnState = useDeepCompareCallback(() => {
96+
const loadPersistedColumnState = useDeepCompareCallback(() => {
9697
columnsPersistedStateRef.current = getPersistedColumnState({
9798
actualColumnKeys: columns.map((column) => column.key),
9899
persistedColumnState: onGetColumnsState?.(),
@@ -110,8 +111,32 @@ export const useColumnState = ({
110111
}, [applyAutoFitState, applyPersistedState, columns, onGetColumnsState]);
111112

112113
return {
113-
applyColumnState,
114+
loadPersistedColumnState,
114115
columnsPersistedStateRef,
115116
applyAndUpdateNewState,
116117
};
117118
};
119+
120+
const removeNullsFromState = (state: ColumnState): Partial<ColumnState> => {
121+
return Object.entries(state).reduce<Partial<ColumnState>>(
122+
(acc, [key, value]) => {
123+
if (value != null) {
124+
acc[key as keyof ColumnState] = value;
125+
}
126+
return acc;
127+
},
128+
{},
129+
);
130+
};
131+
132+
export const areStatesEqual = (
133+
a?: ColumnState[],
134+
b?: ColumnState[],
135+
): boolean => {
136+
if (!a || !b) {
137+
return false;
138+
}
139+
const cleanA = a.map(removeNullsFromState);
140+
const cleanB = b.map(removeNullsFromState);
141+
return dequal(cleanA, cleanB);
142+
};

0 commit comments

Comments
 (0)