@etsoo/react 1.7.32 → 1.7.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 ETSOO
3
+ Copyright (c) 2004-2024 ETSOO® (亿速思维 ®), https://www.etsoo.com
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -21,7 +21,7 @@ test('Tests for EventWatcher', () => {
21
21
  render(<App callback={callback} />);
22
22
  const button = screen.getByRole<HTMLButtonElement>('button');
23
23
  button.click();
24
- expect(callback).toBeCalled();
24
+ expect(callback).toHaveBeenCalled();
25
25
  button.click();
26
- expect(callback).toBeCalledTimes(1);
26
+ expect(callback).toHaveBeenCalledTimes(1);
27
27
  });
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { useAsyncState } from '../src/uses/useAsyncState';
4
- import { act } from 'react-dom/test-utils';
4
+ import { act } from 'react';
5
5
 
6
6
  function App(props: { callback: (state: number) => void }) {
7
7
  const { callback } = props;
@@ -31,7 +31,7 @@ test('Tests for useAsyncState', (done) => {
31
31
 
32
32
  setTimeout(function () {
33
33
  // Expect to happen
34
- expect(callback).lastCalledWith(2);
34
+ expect(callback).toHaveBeenLastCalledWith(2);
35
35
 
36
36
  // Notify jest to complete
37
37
  done();
@@ -11,10 +11,10 @@ export const ScrollerGrid = (props) => {
11
11
  // Rows
12
12
  const [rows, updateRows] = React.useState([]);
13
13
  const setRows = (rows, reset = false) => {
14
- state.loadedItems = rows.length;
14
+ refs.current.loadedItems = rows.length;
15
15
  updateRows(rows);
16
16
  if (!reset && onUpdateRows)
17
- onUpdateRows(rows, state);
17
+ onUpdateRows(rows, refs.current);
18
18
  };
19
19
  // Refs
20
20
  const refs = React.useRef({
@@ -29,17 +29,16 @@ export const ScrollerGrid = (props) => {
29
29
  selectedItems: [],
30
30
  idCache: {}
31
31
  });
32
- const state = refs.current;
33
32
  const ref = React.useRef(null);
34
33
  // Load data
35
34
  const loadDataLocal = (pageAdd = 1) => {
36
35
  // Prevent multiple loadings
37
- if (!state.hasNextPage || state.isNextPageLoading)
36
+ if (!refs.current.hasNextPage || refs.current.isNextPageLoading)
38
37
  return;
39
38
  // Update state
40
- state.isNextPageLoading = true;
39
+ refs.current.isNextPageLoading = true;
41
40
  // Parameters
42
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
41
+ const { currentPage, batchSize, orderBy, orderByAsc, data } = refs.current;
43
42
  const loadProps = {
44
43
  currentPage,
45
44
  batchSize,
@@ -48,37 +47,37 @@ export const ScrollerGrid = (props) => {
48
47
  data
49
48
  };
50
49
  loadData(loadProps).then((result) => {
51
- if (result == null || state.isMounted === false) {
50
+ if (result == null || refs.current.isMounted === false) {
52
51
  return;
53
52
  }
54
- state.isMounted = true;
53
+ refs.current.isMounted = true;
55
54
  const newItems = result.length;
56
- state.lastLoadedItems = newItems;
57
- state.isNextPageLoading = false;
58
- state.hasNextPage = newItems >= batchSize;
55
+ refs.current.lastLoadedItems = newItems;
56
+ refs.current.isNextPageLoading = false;
57
+ refs.current.hasNextPage = newItems >= batchSize;
59
58
  if (pageAdd === 0) {
60
59
  // New items
61
- const newRows = state.lastLoadedItems
60
+ const newRows = refs.current.lastLoadedItems
62
61
  ? [...rows]
63
- .splice(rows.length - state.lastLoadedItems, state.lastLoadedItems)
62
+ .splice(rows.length - refs.current.lastLoadedItems, refs.current.lastLoadedItems)
64
63
  .concat(result)
65
64
  : result;
66
- state.idCache = {};
65
+ refs.current.idCache = {};
67
66
  for (const row of newRows) {
68
67
  const id = row[idField];
69
- state.idCache[id] = null;
68
+ refs.current.idCache[id] = null;
70
69
  }
71
70
  // Update rows
72
71
  setRows(newRows);
73
72
  }
74
73
  else {
75
74
  // Set current page
76
- state.currentPage = state.currentPage + pageAdd;
75
+ refs.current.currentPage = refs.current.currentPage + pageAdd;
77
76
  // Update rows, avoid duplicate items
78
77
  const newRows = [...rows];
79
78
  for (const item of result) {
80
79
  const id = item[idField];
81
- if (state.idCache[id] === undefined) {
80
+ if (refs.current.idCache[id] === undefined) {
82
81
  newRows.push(item);
83
82
  }
84
83
  }
@@ -128,9 +127,9 @@ export const ScrollerGrid = (props) => {
128
127
  lastLoadedItems: undefined,
129
128
  ...add
130
129
  };
131
- Object.assign(state, resetState);
130
+ Object.assign(refs.current, resetState);
132
131
  // Reset items
133
- if (state.isMounted !== false)
132
+ if (refs.current.isMounted !== false)
134
133
  setRows(items, true);
135
134
  };
136
135
  const instance = {
@@ -162,13 +161,13 @@ export const ScrollerGrid = (props) => {
162
161
  },
163
162
  select(rowIndex) {
164
163
  // Select only one item
165
- const selectedItems = state.selectedItems;
164
+ const selectedItems = refs.current.selectedItems;
166
165
  selectedItems[0] = rows[rowIndex];
167
166
  if (onSelectChange)
168
167
  onSelectChange(selectedItems);
169
168
  },
170
169
  selectAll(checked) {
171
- const selectedItems = state.selectedItems;
170
+ const selectedItems = refs.current.selectedItems;
172
171
  rows.forEach((row) => {
173
172
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === row[idField]);
174
173
  if (checked) {
@@ -183,7 +182,7 @@ export const ScrollerGrid = (props) => {
183
182
  onSelectChange(selectedItems);
184
183
  },
185
184
  selectItem(item, checked) {
186
- const selectedItems = state.selectedItems;
185
+ const selectedItems = refs.current.selectedItems;
187
186
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === item[idField]);
188
187
  if (checked) {
189
188
  if (index === -1)
@@ -210,7 +209,7 @@ export const ScrollerGrid = (props) => {
210
209
  React.useImperativeHandle(mRef, () => instance, [rows]);
211
210
  React.useEffect(() => {
212
211
  return () => {
213
- state.isMounted = false;
212
+ refs.current.isMounted = false;
214
213
  };
215
214
  }, []);
216
215
  // Force update to work with the new width and rowHeight
@@ -224,9 +223,9 @@ export const ScrollerGrid = (props) => {
224
223
  // Rows
225
224
  const rowLength = rows.length;
226
225
  // Row count
227
- const rowCount = state.hasNextPage ? rowLength + 1 : rowLength;
226
+ const rowCount = refs.current.hasNextPage ? rowLength + 1 : rowLength;
228
227
  // Auto load data when current page is 0
229
- if (state.currentPage === 0 && state.autoLoad) {
228
+ if (refs.current.currentPage === 0 && refs.current.autoLoad) {
230
229
  const initItems = onInitLoad == null ? undefined : onInitLoad(ref.current);
231
230
  if (initItems)
232
231
  reset(initItems[1], initItems[0]);
@@ -235,13 +234,14 @@ export const ScrollerGrid = (props) => {
235
234
  }
236
235
  // Layout
237
236
  return (React.createElement(React.Fragment, null,
238
- headerRenderer && headerRenderer(state),
237
+ headerRenderer && headerRenderer(refs.current),
239
238
  React.createElement(VariableSizeGrid, { itemKey: ({ columnIndex, rowIndex, data }) => {
240
239
  if (data == null)
241
240
  return [rowIndex, columnIndex].join(',');
242
- return [`${data[idField]}-${rowIndex}`, columnIndex].join(',');
241
+ // ${data[idField]}-${rowIndex} always unique but no cache for the same item
242
+ return [`${data[idField]}`, columnIndex].join(',');
243
243
  }, onItemsRendered: onItemsRenderedLocal, ref: ref, rowCount: rowCount, rowHeight: typeof rowHeight === 'function'
244
244
  ? rowHeight
245
- : () => rowHeight, style: { overflowX: 'hidden' }, width: width, ...rest }, (props) => itemRendererLocal(props, state)),
246
- footerRenderer && footerRenderer(rows, state)));
245
+ : () => rowHeight, style: { overflowX: 'hidden' }, width: width, ...rest }, (props) => itemRendererLocal(props, refs.current)),
246
+ footerRenderer && footerRenderer(rows, refs.current)));
247
247
  };
@@ -29,10 +29,10 @@ export const ScrollerList = (props) => {
29
29
  // Rows
30
30
  const [rows, updateRows] = React.useState([]);
31
31
  const setRows = (rows, reset = false) => {
32
- state.loadedItems = rows.length;
32
+ stateRefs.current.loadedItems = rows.length;
33
33
  updateRows(rows);
34
34
  if (!reset && onUpdateRows)
35
- onUpdateRows(rows, state);
35
+ onUpdateRows(rows, stateRefs.current);
36
36
  };
37
37
  // States
38
38
  const batchSize = GridSizeGet(loadBatchSize, height);
@@ -48,16 +48,16 @@ export const ScrollerList = (props) => {
48
48
  selectedItems: [],
49
49
  idCache: {}
50
50
  });
51
- const state = stateRefs.current;
52
51
  // Load data
53
52
  const loadDataLocal = (pageAdd = 1) => {
54
53
  // Prevent multiple loadings
55
- if (!state.hasNextPage || state.isNextPageLoading)
54
+ if (!stateRefs.current.hasNextPage ||
55
+ stateRefs.current.isNextPageLoading)
56
56
  return;
57
57
  // Update state
58
- state.isNextPageLoading = true;
58
+ stateRefs.current.isNextPageLoading = true;
59
59
  // Parameters
60
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
60
+ const { currentPage, batchSize, orderBy, orderByAsc, data } = stateRefs.current;
61
61
  const loadProps = {
62
62
  currentPage,
63
63
  batchSize,
@@ -66,36 +66,37 @@ export const ScrollerList = (props) => {
66
66
  data
67
67
  };
68
68
  loadData(loadProps).then((result) => {
69
- if (result == null || state.isMounted === false) {
69
+ if (result == null || stateRefs.current.isMounted === false) {
70
70
  return;
71
71
  }
72
- state.isMounted = true;
72
+ stateRefs.current.isMounted = true;
73
73
  const newItems = result.length;
74
- state.lastLoadedItems = newItems;
75
- state.hasNextPage = newItems >= batchSize;
76
- state.isNextPageLoading = false;
74
+ stateRefs.current.lastLoadedItems = newItems;
75
+ stateRefs.current.hasNextPage = newItems >= batchSize;
76
+ stateRefs.current.isNextPageLoading = false;
77
77
  if (pageAdd === 0) {
78
78
  // New items
79
- const newRows = state.lastLoadedItems
79
+ const newRows = stateRefs.current.lastLoadedItems
80
80
  ? [...rows]
81
- .splice(rows.length - state.lastLoadedItems, state.lastLoadedItems)
81
+ .splice(rows.length - stateRefs.current.lastLoadedItems, stateRefs.current.lastLoadedItems)
82
82
  .concat(result)
83
83
  : result;
84
- state.idCache = {};
84
+ stateRefs.current.idCache = {};
85
85
  for (const row of newRows) {
86
86
  const id = row[idField];
87
- state.idCache[id] = null;
87
+ stateRefs.current.idCache[id] = null;
88
88
  }
89
89
  // Update rows
90
90
  setRows(newRows);
91
91
  }
92
92
  else {
93
- state.currentPage = state.currentPage + pageAdd;
93
+ stateRefs.current.currentPage =
94
+ stateRefs.current.currentPage + pageAdd;
94
95
  // Update rows, avoid duplicate items
95
96
  const newRows = [...rows];
96
97
  for (const item of result) {
97
98
  const id = item[idField];
98
- if (state.idCache[id] === undefined) {
99
+ if (stateRefs.current.idCache[id] === undefined) {
99
100
  newRows.push(item);
100
101
  }
101
102
  }
@@ -121,9 +122,9 @@ export const ScrollerList = (props) => {
121
122
  isNextPageLoading: false,
122
123
  ...add
123
124
  };
124
- Object.assign(state, resetState);
125
+ Object.assign(stateRefs.current, resetState);
125
126
  // Reset
126
- if (state.isMounted !== false)
127
+ if (stateRefs.current.isMounted !== false)
127
128
  setRows(items, true);
128
129
  };
129
130
  React.useImperativeHandle(mRef, () => {
@@ -159,7 +160,7 @@ export const ScrollerList = (props) => {
159
160
  React.useEffect(() => {
160
161
  // Return clear function
161
162
  return () => {
162
- state.isMounted = false;
163
+ stateRefs.current.isMounted = false;
163
164
  };
164
165
  }, []);
165
166
  // Row count
@@ -176,9 +177,9 @@ export const ScrollerList = (props) => {
176
177
  onItemsRendered(props);
177
178
  };
178
179
  // Item count
179
- const itemCount = state.hasNextPage ? rowCount + 1 : rowCount;
180
+ const itemCount = stateRefs.current.hasNextPage ? rowCount + 1 : rowCount;
180
181
  // Auto load data when current page is 0
181
- if (state.currentPage === 0 && state.autoLoad) {
182
+ if (stateRefs.current.currentPage === 0 && stateRefs.current.autoLoad) {
182
183
  const initItems = onInitLoad == null ? undefined : onInitLoad(listRef.current);
183
184
  if (initItems)
184
185
  reset(initItems[1], initItems[0]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.7.32",
3
+ "version": "1.7.34",
4
4
  "description": "TypeScript ReactJs UI Independent Framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -49,30 +49,30 @@
49
49
  "@dnd-kit/sortable": "^8.0.0",
50
50
  "@emotion/css": "^11.11.2",
51
51
  "@emotion/react": "^11.11.4",
52
- "@emotion/styled": "^11.11.0",
53
- "@etsoo/appscript": "^1.4.80",
54
- "@etsoo/notificationbase": "^1.1.41",
55
- "@etsoo/shared": "^1.2.33",
56
- "react": "^18.2.0",
57
- "react-dom": "^18.2.0",
58
- "react-router-dom": "^6.22.2",
52
+ "@emotion/styled": "^11.11.5",
53
+ "@etsoo/appscript": "^1.4.84",
54
+ "@etsoo/notificationbase": "^1.1.42",
55
+ "@etsoo/shared": "^1.2.37",
56
+ "react": "^18.3.1",
57
+ "react-dom": "^18.3.1",
58
+ "react-router-dom": "^6.23.0",
59
59
  "react-window": "^1.8.10"
60
60
  },
61
61
  "devDependencies": {
62
- "@babel/cli": "^7.23.9",
63
- "@babel/core": "^7.24.0",
64
- "@babel/plugin-transform-runtime": "^7.24.0",
65
- "@babel/preset-env": "^7.24.0",
66
- "@babel/runtime-corejs3": "^7.24.0",
62
+ "@babel/cli": "^7.24.1",
63
+ "@babel/core": "^7.24.4",
64
+ "@babel/plugin-transform-runtime": "^7.24.3",
65
+ "@babel/preset-env": "^7.24.4",
66
+ "@babel/runtime-corejs3": "^7.24.4",
67
67
  "@testing-library/jest-dom": "^6.4.2",
68
- "@testing-library/react": "^14.2.1",
68
+ "@testing-library/react": "^15.0.5",
69
69
  "@types/jest": "^29.5.12",
70
- "@types/react": "^18.2.62",
71
- "@types/react-dom": "^18.2.19",
70
+ "@types/react": "^18.3.1",
71
+ "@types/react-dom": "^18.3.0",
72
72
  "@types/react-window": "^1.8.8",
73
73
  "jest": "^29.7.0",
74
74
  "jest-environment-jsdom": "^29.7.0",
75
75
  "ts-jest": "^29.1.2",
76
- "typescript": "^5.3.3"
76
+ "typescript": "^5.4.5"
77
77
  }
78
78
  }
@@ -182,10 +182,10 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
182
182
  // Rows
183
183
  const [rows, updateRows] = React.useState<T[]>([]);
184
184
  const setRows = (rows: T[], reset: boolean = false) => {
185
- state.loadedItems = rows.length;
185
+ refs.current.loadedItems = rows.length;
186
186
  updateRows(rows);
187
187
 
188
- if (!reset && onUpdateRows) onUpdateRows(rows, state);
188
+ if (!reset && onUpdateRows) onUpdateRows(rows, refs.current);
189
189
  };
190
190
 
191
191
  // Refs
@@ -201,20 +201,20 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
201
201
  selectedItems: [],
202
202
  idCache: {}
203
203
  });
204
- const state = refs.current;
205
204
 
206
205
  const ref = React.useRef<VariableSizeGrid<T>>(null);
207
206
 
208
207
  // Load data
209
208
  const loadDataLocal = (pageAdd: number = 1) => {
210
209
  // Prevent multiple loadings
211
- if (!state.hasNextPage || state.isNextPageLoading) return;
210
+ if (!refs.current.hasNextPage || refs.current.isNextPageLoading) return;
212
211
 
213
212
  // Update state
214
- state.isNextPageLoading = true;
213
+ refs.current.isNextPageLoading = true;
215
214
 
216
215
  // Parameters
217
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
216
+ const { currentPage, batchSize, orderBy, orderByAsc, data } =
217
+ refs.current;
218
218
 
219
219
  const loadProps: GridLoadDataProps = {
220
220
  currentPage,
@@ -225,45 +225,45 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
225
225
  };
226
226
 
227
227
  loadData(loadProps).then((result) => {
228
- if (result == null || state.isMounted === false) {
228
+ if (result == null || refs.current.isMounted === false) {
229
229
  return;
230
230
  }
231
- state.isMounted = true;
231
+ refs.current.isMounted = true;
232
232
 
233
233
  const newItems = result.length;
234
- state.lastLoadedItems = newItems;
235
- state.isNextPageLoading = false;
236
- state.hasNextPage = newItems >= batchSize;
234
+ refs.current.lastLoadedItems = newItems;
235
+ refs.current.isNextPageLoading = false;
236
+ refs.current.hasNextPage = newItems >= batchSize;
237
237
 
238
238
  if (pageAdd === 0) {
239
239
  // New items
240
- const newRows = state.lastLoadedItems
240
+ const newRows = refs.current.lastLoadedItems
241
241
  ? [...rows]
242
242
  .splice(
243
- rows.length - state.lastLoadedItems,
244
- state.lastLoadedItems
243
+ rows.length - refs.current.lastLoadedItems,
244
+ refs.current.lastLoadedItems
245
245
  )
246
246
  .concat(result)
247
247
  : result;
248
248
 
249
- state.idCache = {};
249
+ refs.current.idCache = {};
250
250
  for (const row of newRows) {
251
251
  const id = row[idField] as any;
252
- state.idCache[id] = null;
252
+ refs.current.idCache[id] = null;
253
253
  }
254
254
 
255
255
  // Update rows
256
256
  setRows(newRows);
257
257
  } else {
258
258
  // Set current page
259
- state.currentPage = state.currentPage + pageAdd;
259
+ refs.current.currentPage = refs.current.currentPage + pageAdd;
260
260
 
261
261
  // Update rows, avoid duplicate items
262
262
  const newRows = [...rows];
263
263
 
264
264
  for (const item of result) {
265
265
  const id = item[idField] as any;
266
- if (state.idCache[id] === undefined) {
266
+ if (refs.current.idCache[id] === undefined) {
267
267
  newRows.push(item);
268
268
  }
269
269
  }
@@ -327,10 +327,10 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
327
327
  lastLoadedItems: undefined,
328
328
  ...add
329
329
  };
330
- Object.assign(state, resetState);
330
+ Object.assign(refs.current, resetState);
331
331
 
332
332
  // Reset items
333
- if (state.isMounted !== false) setRows(items, true);
333
+ if (refs.current.isMounted !== false) setRows(items, true);
334
334
  };
335
335
 
336
336
  const instance: ScrollerGridForwardRef<T> = {
@@ -367,13 +367,13 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
367
367
  },
368
368
  select(rowIndex: number) {
369
369
  // Select only one item
370
- const selectedItems = state.selectedItems;
370
+ const selectedItems = refs.current.selectedItems;
371
371
  selectedItems[0] = rows[rowIndex];
372
372
 
373
373
  if (onSelectChange) onSelectChange(selectedItems);
374
374
  },
375
375
  selectAll(checked: boolean) {
376
- const selectedItems = state.selectedItems;
376
+ const selectedItems = refs.current.selectedItems;
377
377
 
378
378
  rows.forEach((row) => {
379
379
  const index = selectedItems.findIndex(
@@ -390,7 +390,7 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
390
390
  if (onSelectChange) onSelectChange(selectedItems);
391
391
  },
392
392
  selectItem(item: T, checked: boolean) {
393
- const selectedItems = state.selectedItems;
393
+ const selectedItems = refs.current.selectedItems;
394
394
  const index = selectedItems.findIndex(
395
395
  (selectedItem) => selectedItem[idField] === item[idField]
396
396
  );
@@ -423,7 +423,7 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
423
423
 
424
424
  React.useEffect(() => {
425
425
  return () => {
426
- state.isMounted = false;
426
+ refs.current.isMounted = false;
427
427
  };
428
428
  }, []);
429
429
 
@@ -440,10 +440,10 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
440
440
  const rowLength = rows.length;
441
441
 
442
442
  // Row count
443
- const rowCount = state.hasNextPage ? rowLength + 1 : rowLength;
443
+ const rowCount = refs.current.hasNextPage ? rowLength + 1 : rowLength;
444
444
 
445
445
  // Auto load data when current page is 0
446
- if (state.currentPage === 0 && state.autoLoad) {
446
+ if (refs.current.currentPage === 0 && refs.current.autoLoad) {
447
447
  const initItems =
448
448
  onInitLoad == null ? undefined : onInitLoad(ref.current);
449
449
  if (initItems) reset(initItems[1], initItems[0]);
@@ -453,13 +453,12 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
453
453
  // Layout
454
454
  return (
455
455
  <React.Fragment>
456
- {headerRenderer && headerRenderer(state)}
456
+ {headerRenderer && headerRenderer(refs.current)}
457
457
  <VariableSizeGrid<T>
458
458
  itemKey={({ columnIndex, rowIndex, data }) => {
459
459
  if (data == null) return [rowIndex, columnIndex].join(',');
460
- return [`${data[idField]}-${rowIndex}`, columnIndex].join(
461
- ','
462
- );
460
+ // ${data[idField]}-${rowIndex} always unique but no cache for the same item
461
+ return [`${data[idField]}`, columnIndex].join(',');
463
462
  }}
464
463
  onItemsRendered={onItemsRenderedLocal}
465
464
  ref={ref}
@@ -473,9 +472,9 @@ export const ScrollerGrid = <T extends object>(props: ScrollerGridProps<T>) => {
473
472
  width={width}
474
473
  {...rest}
475
474
  >
476
- {(props) => itemRendererLocal(props, state)}
475
+ {(props) => itemRendererLocal(props, refs.current)}
477
476
  </VariableSizeGrid>
478
- {footerRenderer && footerRenderer(rows, state)}
477
+ {footerRenderer && footerRenderer(rows, refs.current)}
479
478
  </React.Fragment>
480
479
  );
481
480
  };
@@ -145,10 +145,10 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
145
145
  // Rows
146
146
  const [rows, updateRows] = React.useState<T[]>([]);
147
147
  const setRows = (rows: T[], reset: boolean = false) => {
148
- state.loadedItems = rows.length;
148
+ stateRefs.current.loadedItems = rows.length;
149
149
  updateRows(rows);
150
150
 
151
- if (!reset && onUpdateRows) onUpdateRows(rows, state);
151
+ if (!reset && onUpdateRows) onUpdateRows(rows, stateRefs.current);
152
152
  };
153
153
 
154
154
  // States
@@ -165,18 +165,22 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
165
165
  selectedItems: [],
166
166
  idCache: {}
167
167
  });
168
- const state = stateRefs.current;
169
168
 
170
169
  // Load data
171
170
  const loadDataLocal = (pageAdd: number = 1) => {
172
171
  // Prevent multiple loadings
173
- if (!state.hasNextPage || state.isNextPageLoading) return;
172
+ if (
173
+ !stateRefs.current.hasNextPage ||
174
+ stateRefs.current.isNextPageLoading
175
+ )
176
+ return;
174
177
 
175
178
  // Update state
176
- state.isNextPageLoading = true;
179
+ stateRefs.current.isNextPageLoading = true;
177
180
 
178
181
  // Parameters
179
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
182
+ const { currentPage, batchSize, orderBy, orderByAsc, data } =
183
+ stateRefs.current;
180
184
 
181
185
  const loadProps: GridLoadDataProps = {
182
186
  currentPage,
@@ -187,44 +191,45 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
187
191
  };
188
192
 
189
193
  loadData(loadProps).then((result) => {
190
- if (result == null || state.isMounted === false) {
194
+ if (result == null || stateRefs.current.isMounted === false) {
191
195
  return;
192
196
  }
193
- state.isMounted = true;
197
+ stateRefs.current.isMounted = true;
194
198
 
195
199
  const newItems = result.length;
196
- state.lastLoadedItems = newItems;
197
- state.hasNextPage = newItems >= batchSize;
198
- state.isNextPageLoading = false;
200
+ stateRefs.current.lastLoadedItems = newItems;
201
+ stateRefs.current.hasNextPage = newItems >= batchSize;
202
+ stateRefs.current.isNextPageLoading = false;
199
203
 
200
204
  if (pageAdd === 0) {
201
205
  // New items
202
- const newRows = state.lastLoadedItems
206
+ const newRows = stateRefs.current.lastLoadedItems
203
207
  ? [...rows]
204
208
  .splice(
205
- rows.length - state.lastLoadedItems,
206
- state.lastLoadedItems
209
+ rows.length - stateRefs.current.lastLoadedItems,
210
+ stateRefs.current.lastLoadedItems
207
211
  )
208
212
  .concat(result)
209
213
  : result;
210
214
 
211
- state.idCache = {};
215
+ stateRefs.current.idCache = {};
212
216
  for (const row of newRows) {
213
217
  const id = row[idField] as any;
214
- state.idCache[id] = null;
218
+ stateRefs.current.idCache[id] = null;
215
219
  }
216
220
 
217
221
  // Update rows
218
222
  setRows(newRows);
219
223
  } else {
220
- state.currentPage = state.currentPage + pageAdd;
224
+ stateRefs.current.currentPage =
225
+ stateRefs.current.currentPage + pageAdd;
221
226
 
222
227
  // Update rows, avoid duplicate items
223
228
  const newRows = [...rows];
224
229
 
225
230
  for (const item of result) {
226
231
  const id = item[idField] as any;
227
- if (state.idCache[id] === undefined) {
232
+ if (stateRefs.current.idCache[id] === undefined) {
228
233
  newRows.push(item);
229
234
  }
230
235
  }
@@ -253,10 +258,10 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
253
258
  isNextPageLoading: false,
254
259
  ...add
255
260
  };
256
- Object.assign(state, resetState);
261
+ Object.assign(stateRefs.current, resetState);
257
262
 
258
263
  // Reset
259
- if (state.isMounted !== false) setRows(items, true);
264
+ if (stateRefs.current.isMounted !== false) setRows(items, true);
260
265
  };
261
266
 
262
267
  React.useImperativeHandle(
@@ -301,7 +306,7 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
301
306
  React.useEffect(() => {
302
307
  // Return clear function
303
308
  return () => {
304
- state.isMounted = false;
309
+ stateRefs.current.isMounted = false;
305
310
  };
306
311
  }, []);
307
312
 
@@ -322,10 +327,10 @@ export const ScrollerList = <T extends object>(props: ScrollerListProps<T>) => {
322
327
  };
323
328
 
324
329
  // Item count
325
- const itemCount = state.hasNextPage ? rowCount + 1 : rowCount;
330
+ const itemCount = stateRefs.current.hasNextPage ? rowCount + 1 : rowCount;
326
331
 
327
332
  // Auto load data when current page is 0
328
- if (state.currentPage === 0 && state.autoLoad) {
333
+ if (stateRefs.current.currentPage === 0 && stateRefs.current.autoLoad) {
329
334
  const initItems =
330
335
  onInitLoad == null ? undefined : onInitLoad(listRef.current);
331
336
  if (initItems) reset(initItems[1], initItems[0]);