swr
swr copied to clipboard
Multiple consumers of the same cache key all paused if only one `isPaused()` evaluates to true
Bug report
Description / Observed Behavior
We are using SWR in a react-native application with react-navigation. React Navigation stack navigator allows multiple screens to be mounted with one of them (the top of the stack) actually being focused. This allows quick switching to a previous screen without re-rendering from scratch.
In order to avoid SWR reloading data for all screens in the stack whenever a revalidate event is triggered (focus, etc.) we were hoping to use isPaused()
like this:
const isFocused = useIsFocused();
const { data, error, mutate, isValidating } = useSWR(["get", "/api/123"], apiRequest, {
isPaused: () => {
return !isFocused;
},
});
What's the problem?
When two screens are loading data for the same cache key, one may be focused and the other would not be focused. In this situation SWR is not making a request to load data for the focused screen. We know it is the isPaused
that is causing the issue because if we remove the isPaused
config in the un-focused screen everything loads fine.
I have also confirmed that isPaused
is called for both usages of the hook, each screen evaluating to the expected value based on its focus state.
Expected Behavior
I expect useSWR
to load data and keep it up-to-date when isPaused
evaluates to false
regardless of if another hook in use for the same cache key has an isPaused
that evaluates to true
. I only want something to be paused if all hooks consuming the same cache key evaluate isPaused
to true
.
Repro Steps / Code Example
Hopefully the code and scenario given above gives a bit of insight into a repro. Feel free to request me to make a repro if you think it is important.
Additional Context
Issue originally discovered on SWR 1.3.0
but I am able to reproduce it just the same on 2.0.0
.
Thanks in advance for taking a look! Jack (& The Questmate Team 🚀)
Repro: https://codesandbox.io/s/swr-ispaused-bx1i3z?file=/src/App.js
after setting isPause = true
, data will never be able to update by auto revalidation.
I think the reason of this problem is beacause we only call the first revalidators when doing event revalidation. So if the first revalidators rececive isPause: () => false
, it will prevent other hooks trigger event revalidation.
https://github.com/vercel/swr/blob/06a644129e66982f2d837047be797df2e506b228/core/use-swr.ts#L238-L250
https://github.com/vercel/swr/blob/06a644129e66982f2d837047be797df2e506b228/_internal/utils/cache.ts#L17-L24
@promer94 Thanks for looking into this and adding a repro! 🙏
I think this issue relates to issue #2394
It does seem like it could be related. But I think the use-case for the issue described here is more concrete than the one linked to as it seems to have been closed due to a lack of understanding of why it should be fixed.
Would anyone (@promer94) have ideas on how to work around this problem and get the desired behavior -- One consumer of the cache key not paused, then revalidations should occur?
Still appears to be an issue in 2.2.5