Skip to content

Commit 675dc30

Browse files
jluyauLFDanLuyihuiliao
authored
fix: do not dispatch loadMore if hook is still in loading state (#8571)
* do not dispatch loadMore if hook is still in loading state * fix lint * fis lint * add test --------- Co-authored-by: Daniel Lu <[email protected]> Co-authored-by: Yihui Liao <[email protected]>
1 parent 5653514 commit 675dc30

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

packages/@react-spectrum/s2/stories/TableView.stories.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,23 @@
1111
*/
1212

1313
import {action} from '@storybook/addon-actions';
14-
import {ActionButton, Cell, Column, Content, Heading, IllustratedMessage, Link, MenuItem, MenuSection, Row, TableBody, TableHeader, TableView, TableViewProps, Text} from '../src';
14+
import {
15+
ActionButton,
16+
Cell,
17+
Column,
18+
Content,
19+
Heading,
20+
IllustratedMessage,
21+
Link,
22+
MenuItem,
23+
MenuSection,
24+
Row,
25+
TableBody,
26+
TableHeader,
27+
TableView,
28+
TableViewProps,
29+
Text
30+
} from '../src';
1531
import {categorizeArgTypes} from './utils';
1632
import Filter from '../s2wf-icons/S2_Icon_Filter_20_N.svg';
1733
import FolderOpen from '../spectrum-illustrations/linear/FolderOpen';

packages/@react-stately/data/src/useAsyncList.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ export function useAsyncList<T, C = string>(options: AsyncListOptions<T, C>): As
339339
},
340340
loadMore() {
341341
// Ignore if already loading more or if performing server side filtering.
342-
if (data.state === 'loadingMore' || data.state === 'filtering' || data.cursor == null) {
342+
if (data.state === 'loading' || data.state === 'loadingMore' || data.state === 'filtering' || data.cursor == null) {
343343
return;
344344
}
345345

packages/@react-stately/data/test/useAsyncList.test.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,56 @@ describe('useAsyncList', () => {
334334
expect(result.current.items).toEqual(ITEMS);
335335
});
336336

337+
it('should prevent loadMore from firing if in the middle of a load', async () => {
338+
let load = jest.fn().mockImplementation(getItems);
339+
let {result} = renderHook(
340+
() => useAsyncList({load})
341+
);
342+
343+
expect(load).toHaveBeenCalledTimes(1);
344+
expect(result.current.isLoading).toBe(true);
345+
expect(result.current.items).toEqual([]);
346+
347+
await act(async () => {
348+
result.current.loadMore();
349+
});
350+
351+
expect(result.current.isLoading).toBe(true);
352+
expect(result.current.items).toEqual([]);
353+
expect(load).toHaveBeenCalledTimes(1);
354+
355+
await act(async () => {
356+
jest.runAllTimers();
357+
});
358+
359+
expect(result.current.isLoading).toBe(false);
360+
expect(result.current.items).toEqual(ITEMS);
361+
362+
await act(async () => {
363+
result.current.reload();
364+
});
365+
366+
expect(result.current.isLoading).toBe(true);
367+
expect(result.current.items).toEqual([]);
368+
expect(load).toHaveBeenCalledTimes(2);
369+
370+
await act(async () => {
371+
result.current.loadMore();
372+
});
373+
374+
expect(result.current.isLoading).toBe(true);
375+
expect(result.current.items).toEqual([]);
376+
expect(load).toHaveBeenCalledTimes(2);
377+
378+
await act(async () => {
379+
jest.runAllTimers();
380+
});
381+
382+
expect(result.current.isLoading).toBe(false);
383+
expect(result.current.items).toEqual(ITEMS);
384+
});
385+
386+
337387
it('should ignore duplicate loads where first resolves first', async () => {
338388
let load = jest.fn().mockImplementation(getItems2);
339389
let sort = jest.fn().mockImplementation(() => new Promise(resolve => setTimeout(() => resolve({items: ITEMS2}), 100)));

0 commit comments

Comments
 (0)