react
react copied to clipboard
[React 19] Upgrading React causes infinite refetching
Summary
The reproduction is using Relay, but I came as this seems closer to a bug in React than Relay.
https://stackblitz.com/@cometkim/collections/react-relay-suspend-loop
With this basic setup, using useLazyLoadQuery with network-only to make a new fetch() call on render. The code works fine in v18, but after upgrading to v19, it starts remounting an element infinitely.
- React v18: No issues
- React v19: No differences, but the children including the suspense boundary is unexpectedly unmounted, resulting in an infinite refetch loop.
- React v19 workaround 1: Removing
<StrictMode>seems to solve the issue. - React v19 workaround 2: Wrap the parent (which is just a context provider with nothing special) by one more
<Suspense>boundary. It seems to do not make sense, but it works.
The expected behavior is that the <Suspense> boundary is retained stable, and the <NetworkOnly> is rendered after waiting for the QueryResource fulfilled.
However, this seems to me like the <Suspense> could suspend itself.
So for starters, I would just like to ask, what exactly you are looking to resolve this? Like for say, we can stay on the v18. Is upgradation so much important ?
built an app to get paid for this PR https://www.n0va-io.com/discover/facebook/react
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Updated the example to 19.0.0-rc.1, and the issue is still there...
Updated to 19.0.0 which is the stable release
I also faced the same issue
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
It's still reproducible, and no fixes are referenced
Updated example to v19.1.0, it's still happening consistently.
Same here we have useLazyLoadQuery with a refetchable fragment inside and it suspense indefinitely
This still happens
Here to say that adding a Suspense as a parent to the Suspense that was causing this exact issue for me solved it for me (React Native). Suspend your Suspenses folks.
Also running into this when using network-only which I had been using in order to ensure that fresh data was always fetched when opening a modal (even if the same modal had been closed/reopened). Since React 19 seems to fully unmount/remount the component and there is no way to persist data within a suspended component, it seems that React requires that the fetch promise is cached somehow outside of React (which basically makes it impossible to tie the fetch to "initial render" if your component is inside a <Suspense>)
For my use case I was able to workaround it by going back to store-or-cache fetch policy, but creating a new Relay environment with an empty cache and wrapping my modal in that to ensure it fetches fresh data. My modal now looks like this:
const rootEnvironment = useRelayEnvironment()
const [environment] = useState(() => {
return new Environment({
network: rootEnvironment.getNetwork(),
store: new Store(new RecordSource()),
})
})
return (
<RelayEnvironmentProvider environment={environment}>
<Suspense fallback={<Loading />}>
<ComponentThatWillDoSomeFetching />
</Suspense>
</RelayEnvironmentProvider>
This is janky, and having no mechanism in React to have statefulness that persists between suspend/unsuspend for a component just seems entirely broken to me.
Updated examples to React v19.2.0. The issue still exists.