When you submit a form you might change some data, and the data currently shown on the page could be stale (outdated). Also, when you change the search params, the data on the page should be refreshed so the user can see the most up-to-date version of that page or screen.
In React Router 6.4+ and by extension Remix, you export a loader function that fetches data to be used for each route. And revalidation is when React Router call the loader functions so your page will always remain up-to-date in the above mentioned and similar cases.
In some cases where a nested route changes, React Router does some optimization and doesn't call all the matching loaders again, just necessary ones. But, on form submission and search param changes, every loader will be re-validated since they might depend on the search params to retrieve data.
When you have multiple nested routes, usually upper routes can be layout that don't change that often, for example there are very few cases where the root loader that might return user name and profile picture URL need to be refreshed.
React Router gives you a declarative way to define relationship between
data (loader) and view (React component), and keeps the view up-to-date
by giving it the most recent data. Though, there are times you want to
opt-out of this functionality to optimize traffic or reduce latency
of higher priority routes, this is done through shouldRevalidate
function.
A good example is, when you change page
search param in a paginated
table nested inside a couple routes; or when loaders are called, and
the user is offline at that time, the loaders might throw an error
which makes your React component unmount, and renders the nearest
ErrorBoundary, this is very cool, declarative and automatic. Unless, you
need to keep your UI on the screen, even if the loaders need to be called again
but it is not possible, you can tell React Router not to re-validate (calling
loaders) by returning false
from shouldRevalidate, like this:
// root.tsx
import type { ShouldRevalidateFunction } from "@remix-run/react"
export const shouldRevalidate: ShouldRevalidateFunction = ({
defaultShouldRevalidate,
}) => {
if ("onLine" in navigator && navigator.onLine === false) {
return false
}
return defaultShouldRevalidate
}
It is recommended that your return
defaultShouldRevalidate
if no criteria that you provided are met, so React Router can still keep the default behavior, which is usually the desired behavior. As demonstrated in the code snippet above.
React Router provides many parameters so you have as much information
as possible to base your criteria on. For example, in the case of form
submission you have access to formMethod
, formAction
, formEncType
,
formData
, json
.
You even have access to actionResult
that is returned from the action
function, which you usually read from useActionData
in your UI, this
enables very advanced use-cases like conditional revalidation based on
action results, which is a fancy way for saying you can control revalidation
based on the result of your actions.
There are many other parameters provided to use, you can learn more about
shouldRevalidate
, it's params and it is behavior on
React Router docs