React Router 7 Revalidation
Revalidation is the process of re-running route loaders to fetch fresh data. React Router automatically revalidates loaders in certain scenarios, but you can control this behavior using shouldRevalidate.
Why does revalidation matter?
- Performance: Prevent unnecessary data fetching
- UX: Keep data fresh when needed
- Server costs: Reduce SSR load by skipping redundant calls
- Flexibility: Fine-tune when each route refreshes its data
Loaders
Loaders fetch data for routes before rendering:
// routes/dashboard.jsx
export const loader = async () => {
const data = await fetchDashboardData();
return { data };
};
export default function Dashboard({ loaderData }) {
return <div>{loaderData.data}</div>;
}
The Revalidation Flow
Route Hierarchy & Independent Revalidation
Each route decides independently whether to revalidate:
Key Point: Root returning false doesn't prevent children from revalidating!
When Revalidation Happens
Default Revalidation Triggers
React Router revalidates loaders in these scenarios:
1. Navigation Between Routes
// User navigates: /dashboard → /settings
// Both /dashboard and /settings loaders run
2. Form Submissions (React Router Forms)
<Form method="post" action="/login">
<input name="email" />
<button>Login</button>
</Form>
// After submission, loaders revalidate
3. Action Completion
export const action = async ({ request }) => {
await updateUser(request);
return { success: true };
};
// After action completes, loaders revalidate
4. Manual Revalidation
const revalidator = useRevalidator();
revalidator.revalidate();
// Triggers revalidation immediately
5. URL Parameter Changes
// Navigate: /users/1 → /users/2
// Loader revalidates with new params
6. Search Parameter Changes
// Navigate: /users → /users?sort=name
// Loader revalidates with new search params
shouldRevalidate Function
Controls whether a route's loader should re-run during revalidation.
Example
export const shouldRevalidate = (args) => {
return true; // or false
};
Available Parameters
export const shouldRevalidate = ({
currentUrl, // URL before navigation/action
nextUrl, // URL after navigation/action
currentParams, // Route params before
nextParams, // Route params after
formMethod, // "GET", "POST", etc. (React Router Forms only)
formAction, // Form action URL
formEncType, // Form encoding type
formData, // Submitted form data
actionResult, // Return value from action
defaultShouldRevalidate, // What React Router would do by default
}) => {
// Your logic here
return true;
};
Decision Flow
What is defaultShouldRevalidate?
A boolean parameter passed to shouldRevalidate that indicates what React Router would do by default.
When it is true?
useRevalidator().revalidate()is called- Initial page load
- Standard navigation
- etc
Why This Matters in Board Web
The root loader in board-web/app/root.jsx fetch authenticated user data and pass it to AuthProvider. Without guard, every navigation would re-fetch that user on every route transition, causing network traffic that might be unnecessary. Our custom shouldRevalidate limits those calls while still allowing manual refreshes via useRevalidator().revalidate().
export function shouldRevalidate({ currentUrl, nextUrl, formMethod, defaultShouldRevalidate }) {
....
// Skip revalidation every page navigation to avoid multiple root loader calls.
if (currentUrl?.href !== nextUrl?.href) {
return false
}
// Fallback to the router's default logic (includes manual `useRevalidator` triggers).
return defaultShouldRevalidate
}