-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling setSize
before pages finish loading causes useSWRInfinite
to trigger multiple requests
#3001
Comments
For now, it is possible to work around the issue using this wrapper function: import { useCallback } from "react";
import useSWRInfinite, { SWRInfiniteHook } from "swr/dist/infinite";
export const useSWRInfinitePatched: SWRInfiniteHook =
function useSWRInfinitePatched(this: unknown, ...params: unknown[]) {
const hook = useSWRInfinite.apply(this, params as any);
const originalSetSize = hook.setSize;
hook.setSize = useCallback(
(sizeOrFn) => {
const newSize =
typeof sizeOrFn === "function" ? sizeOrFn(hook.size) : sizeOrFn;
// Patch for
// https://github.com/vercel/swr/issues/3001
if (newSize === hook.size) {
// Based on
// https://github.com/vercel/swr/blob/1585a3e37d90ad0df8097b099db38f1afb43c95d/src/infinite/index.ts#L295
return Promise.resolve() as Promise<undefined>;
} else {
return originalSetSize(newSize);
}
},
[originalSetSize, hook.size]
);
return hook;
} as unknown as SWRInfiniteHook; |
hello! i'm working on an email app with infinite loading and was struggling to figure out why our api was getting pinged multiple times on fast scroll scenarios. in our case, we have optimistic ui that was loading and increasing the size of the infinite loader, but the api wasn't finished with a subsequent api call. the crux of the issue is that the useSWRInfinite is playing "catch up" with our optimistic ui. for example, the optimisic ui would set the size to 10, but the api would be still loading the 2nd page of data. I believe that this probably goes against the use case of useSWRInfinite, where one page should theoretically be loaded before another page can even start loading, and I think this is apparent in the source code: https://github.com/vercel/swr/blob/main/src/infinite/index.ts#L184 in the "catch up scenario", the 10th call of the fetcher function notices that the pages 2-10 need loading, so it will trigger an api request for pages 2-10, but the 9th call of the fetcher function notices that pages 2-9 need loading so it will trigger an additional api request for pages 2-9, etc. I figured that this probably won't be fixed with SWR (since it goes against default behavior), and I also have a workaround solution that uses a local size & setSize function + a useEffect to follow the incremental page increases without triggering useSWRInfinite's default functionality for loading the entirety of the undefined dataset hopefully this helps too!
|
Bug report
Description / Observed Behavior
In an infinite scroll scenario,
useSWRInfinite
would trigger tens of duplicated requests in the span of a few milliseconds.Expected Behavior
SWR should have triggered only one request
Repro Steps / Code Example
Minimal reproduction set up here: https://github.com/FelixZY/swr-setsize-bug-repro
Using the linked reproduction:
npm start
Expected:
The console output should show
Actual:
Actual output (example)
Screencast.from.2024-08-08.13.31.48.webm
Additional Context
SWR version: 2.2.5
It seems the crucial step is for
setSize
to be called multiple times before loading has actually finished. You can confirm this by removingdelay
here:https://github.com/FelixZY/swr-setsize-bug-repro/blob/22ae6eb8181b227739fd0512444501a3a14bb3d6/src/App.js#L20
The text was updated successfully, but these errors were encountered: