Limits of Remix shouldRevalidate when skipping a loader's re-fetch after actions
0 reputation · 08 Sept 2025, 08:42 UTC
0 reputation · 08 Sept 2025, 08:42 UTC
Remix runs each route's loader on the server before rendering, and after an action it re-runs the loaders for all active routes by default so the UI reflects the mutation. The documented shouldRevalidate route export can return false to skip a loader during a navigation or after an action, using context about the current and next request.
The design question concerns a nested route where one loader performs an expensive query that rarely changes, while sibling loaders must stay fresh after every action. Because nested loaders run in parallel, that single slow loader still determines how long the batch takes. The goal is to suppress re-fetching only that loader without introducing stale UI, since the underlying data can also change independently of client actions.
shouldRevalidate opt out per route?35275 reputation · 08 Sept 2025, 11:57 UTC
By default, Remix re-runs the loader for every active route on the page after an action completes. This ensures the UI remains synchronized with the server state. Because nested loaders are executed in parallel, the total time to resolve the revalidation batch is determined by the slowest loader in the hierarchy.
You can opt out of this behavior on a per-route basis using the shouldRevalidate export. Returning false from this function tells Remix to skip that specific route's loader for the current revalidation trigger, allowing the rest of the active routes to refresh normally.
The shouldRevalidate function provides context that can be used to determine if a skip is safe. The reliability of these signals depends on the nature of your data:
currentParams and nextParams is a highly reliable signal. If the route parameters have not changed and the action did not target a resource linked to those parameters, the data is likely still valid.actionResult (or actionData) can be used to inspect what actually changed. If the action returns a specific flag or status indicating that the "expensive" data was not touched, skipping is safer.Assumption: This assumes a standard Remix SSR setup. If you are using custom data routers or specific React Router adapters, the argument signatures for shouldRevalidate may vary slightly.
Skipping a loader introduces the risk of stale UI, particularly when data can be modified by external sources (e.g., background jobs, other users, or scheduled tasks) that the client-side action cannot track.
To bound these risks, consider these strategies:
useRevalidator().revalidate() to force a refresh of all loaders when a specific client-side event occurs.useNavigation to update the UI immediately, reducing the perceived need for an immediate server-side re-fetch of the expensive loader.To verify your implementation, use these scoped checks:
console.log inside both the shouldRevalidate function and the loader to confirm the skip logic triggers as expected.Diagnostic Note: Are you using a shared cache (like Redis) for the expensive loader? If so, the performance bottleneck may be the network round-trip rather than the query execution itself.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.