-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
[Bug]: Fetcher Revalidation Race Condition (Remix) #10473
Comments
@brophdawg11 I believe we're seeing this in our application, but the discord link with reproduction steps isn't accessible. Can you post the reproduction steps? Thanks! |
The reproduction is here but I'm not sure it quite reproduces on stackblitz because they serve JS files from a service worker so we don't hit the underlying race condition: https://stackblitz.com/edit/remix-run-remix-qdy2d2 |
@brophdawg11 I hacked together a "fix" in my fork of Remix: n8agrin/remix#1 The pattern I'm noticing is that in many contexts (shouldRevalidate being just one), Remix attempts to access routeModules assuming that all possible required modules are always loaded. We're seeing that's not always the case in this issue and in the issue I'm trying to fix in this other PR: remix-run/remix#6409 My unsolicited 2c is that access to routeModules should be behind an interface that can: retrieve from local cache, load from the network or throw. I'm trying to begin to see what that would feel like in this pr, and I don't love how the async nature of the problem demands more and more of the code be refactored to manage one small dependency. Note that I tried the reload approach (as in remix-run/remix#6409), but that doesn't work. It creates an infinite loop within the shouldRevalide call (no surprise I suppose). Do you have any ideas? Maybe we need to bite the bullet and do the async refactor. |
@brophdawg11 just realized some of my edits span react-router and they aren’t captured here. I’ll upload the diff later. In particular I changed the createShouldRevalidate generator to async load a route module if it’s not found, which solves this issue |
This is fixed by #10623 and should be available in the next release. |
@n8agrin I don't think we want to make |
@brophdawg11 let me try to explain the bug we're seeing. It's not readily clear that the fix for this issue will fix our particular problem:
If I understand your patch correctly, it doesn't trigger shouldRevalidate on initial route load, because the routeModule may not yet be loaded. My mental model about how this works is confused, because it seems like the synchronous logic assumes all of the route modules must be loaded, when they clearly may not be. Two questions:
|
🤖 Hello there, We just published version Thanks! |
It's hard to speculate on your specific root cause without a reproduction. If it's related to a The mental model of "data routing" boils down to data loading and rendering being completely decoupled. All data loading completes before we even inform the react layer of the matched components for the new route. In Remix, part of the "load" step is loading the route module and putting it in the route modules cache. UI concerns, such as rendering the matches don't happen for new routes unless the load was successful. If the route module fails to load, Remix performs a hard refresh via
|
@brophdawg11 awesome thanks for that |
@brophdawg11 this didn't seem to fix our issue. I'll try to craft a repro, post it and/or provide a patch |
🤖 Hello there, We just published version Thanks! |
What version of React Router are you using?
6.11.0
Steps to Reproduce
https://discord.com/channels/@me/1105622443453857842/1105623069365649458
It seems there's a race condition in Remix when the
fetcher.load
kicks off on initial render, and then the subsequent render-drivennavigate
triggers ashouldRevalidate
call on the fetcher - and if the fetcher has not yet loaded the route module for the Remix route it bombs out.The fetcher probably shouldn't attempt to revalidate at all since it's tied to a hardcoded route. With navigational loaders even on reused routes we still want to call
shouldRevalidate
so folks can opt-in, but with fetchers they can manually re-trigger viafetcher.load
if necessary.I do worry this fix might still have the same race condition bug if the render-driven navigation comes from
useSubmit
- since fetchers should attempt to revalidate after actions. But really GET-driven initial renders shouldn't trigger mutations. Worth digging a bit deeper into the Remix side of things to see if there's any avenues to look into there.Expected Behavior
Fetcher does not try to revalidate and does not call
shouldRevalidate
Actual Behavior
Fetcher is trying to revalidate before the route module loads.
The text was updated successfully, but these errors were encountered: