Skip to content

Commit

Permalink
fix: refetching on infinite query when a page was deleted (#1124)
Browse files Browse the repository at this point in the history
* test: add more test

* feat: update infinite fetch

* refactoring

* refactoring

* refactoring
  • Loading branch information
p-siriphanthong committed Oct 3, 2020
1 parent b4aa576 commit 6f2ae92
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,10 @@ export class Query<TResult, TError> {
cursor = config.getFetchMore(lastPage, pages)
}

if (!Boolean(cursor) && typeof lastPage !== 'undefined') {
return pages
}

const page = await config.queryFn(...params, cursor)

return prepend ? [page, ...pages] : [...pages, page]
Expand Down
137 changes: 135 additions & 2 deletions src/react/tests/useInfiniteQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const initialItems = (page: number): Result => {
}
}

const fetchItems = async (page: number, ts: number): Promise<Result> => {
const fetchItems = async (page: number, ts: number, nextId?: any): Promise<Result> => {
await sleep(10)
return {
items: [...new Array(10)].fill(null).map((_, d) => page * pageSize + d),
nextId: page + 1,
nextId: nextId ?? page + 1,
ts,
}
}
Expand Down Expand Up @@ -1063,4 +1063,137 @@ describe('useInfiniteQuery', () => {
// ensure that Item: 4 is no longer rendered
expect(rendered.queryAllByText('Item: 4')).toHaveLength(0)
})

it('should compute canFetchMore correctly for falsy getFetchMore return value on refetching', async () => {
const key = queryKey()
const MAX = 2

function Page() {
const fetchCountRef = React.useRef(0)
const [isRemovedLastPage, setIsRemovedLastPage] = React.useState<boolean>(
false
)
const {
status,
data,
error,
isFetching,
isFetchingMore,
fetchMore,
canFetchMore,
refetch,
} = useInfiniteQuery<Result, Error, [string, number]>(
key,
(_key, nextId = 0) =>
fetchItems(
nextId,
fetchCountRef.current++,
nextId === MAX || (nextId === MAX - 1 && isRemovedLastPage)
? false
: undefined
),
{
getFetchMore: (lastGroup, _allGroups) => lastGroup.nextId,
}
)

return (
<div>
<h1>Pagination</h1>
{status === 'loading' ? (
'Loading...'
) : status === 'error' ? (
<span>Error: {error?.message}</span>
) : (
<>
<div>Data:</div>
{data?.map((page, i) => (
<div key={i}>
<div>
Page {i}: {page.ts}
</div>
<div key={i}>
{page.items.map(item => (
<p key={item}>Item: {item}</p>
))}
</div>
</div>
))}
<div>
<button
onClick={() => fetchMore()}
disabled={!canFetchMore || Boolean(isFetchingMore)}
>
{isFetchingMore
? 'Loading more...'
: canFetchMore
? 'Load More'
: 'Nothing more to load'}
</button>
<button onClick={() => refetch()}>Refetch</button>
<button onClick={() => setIsRemovedLastPage(true)}>
Remove Last Page
</button>
</div>
<div>
{isFetching && !isFetchingMore
? 'Background Updating...'
: null}
</div>
</>
)}
</div>
)
}

const rendered = render(<Page />)

rendered.getByText('Loading...')

await waitFor(() => {
rendered.getByText('Item: 9')
rendered.getByText('Page 0: 0')
})

fireEvent.click(rendered.getByText('Load More'))

await waitFor(() => rendered.getByText('Loading more...'))

await waitFor(() => {
rendered.getByText('Item: 19')
rendered.getByText('Page 0: 0')
rendered.getByText('Page 1: 1')
})

fireEvent.click(rendered.getByText('Load More'))

await waitFor(() => rendered.getByText('Loading more...'))

await waitFor(() => {
rendered.getByText('Item: 29')
rendered.getByText('Page 0: 0')
rendered.getByText('Page 1: 1')
rendered.getByText('Page 2: 2')
})

rendered.getByText('Nothing more to load')

fireEvent.click(rendered.getByText('Remove Last Page'))

await waitForMs(10)

fireEvent.click(rendered.getByText('Refetch'))

await waitFor(() => rendered.getByText('Background Updating...'))

await waitFor(() => {
rendered.getByText('Page 0: 3')
rendered.getByText('Page 1: 4')
})

expect(rendered.queryByText('Item: 29')).toBeNull()
expect(rendered.queryByText('Page 2: 5')).toBeNull()

rendered.getByText('Nothing more to load')
})
})

0 comments on commit 6f2ae92

Please sign in to comment.