Skip to main content

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
}

Further Reading