Skip to content

Commit 1678d41

Browse files
feat(react-router): stabilize useRevalidator's revalidate (#13542)
Co-authored-by: Michaël De Boey <info@michaeldeboey.be>
1 parent 5af3eaa commit 1678d41

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

.changeset/healthy-readers-kick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
Stabilize `useRevalidator`'s `revalidate` function

packages/react-router/__tests__/use-revalidator-test.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,48 @@ describe("useRevalidator", () => {
283283

284284
expect(count).toBe(1);
285285
});
286+
287+
it("is stable across revalidation changes", async () => {
288+
let uiCount = 0;
289+
let stableCount = 0;
290+
let unstableCount = 0;
291+
let router = createMemoryRouter(
292+
[
293+
{
294+
id: "root",
295+
path: "/",
296+
loader: () => ++uiCount,
297+
Component() {
298+
let { revalidate, state } = useRevalidator();
299+
300+
React.useEffect(() => void stableCount++, [revalidate]);
301+
React.useEffect(() => void unstableCount++, [state]);
302+
303+
return (
304+
<button onClick={() => revalidate()}>
305+
Revalidate: {useLoaderData()}
306+
</button>
307+
);
308+
},
309+
},
310+
],
311+
{
312+
hydrationData: {
313+
loaderData: { root: 0 },
314+
},
315+
}
316+
);
317+
318+
render(<RouterProvider router={router} />);
319+
320+
fireEvent.click(screen.getByText("Revalidate: 0"));
321+
await waitFor(() => screen.getByText("Revalidate: 1"));
322+
323+
fireEvent.click(screen.getByText("Revalidate: 1"));
324+
await waitFor(() => screen.getByText("Revalidate: 2"));
325+
326+
// idle -> loading -> idle -> loading -> idle
327+
expect(unstableCount).toBe(5);
328+
expect(stableCount).toBe(1);
329+
});
286330
});

packages/react-router/lib/hooks.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,17 +1043,19 @@ export function useNavigation() {
10431043
10441044
@category Hooks
10451045
*/
1046-
export function useRevalidator() {
1046+
export function useRevalidator(): {
1047+
revalidate: () => Promise<void>;
1048+
state: DataRouter["state"]["revalidation"];
1049+
} {
10471050
let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);
10481051
let state = useDataRouterState(DataRouterStateHook.UseRevalidator);
1052+
let revalidate = React.useCallback(async () => {
1053+
await dataRouterContext.router.revalidate();
1054+
}, [dataRouterContext.router]);
1055+
10491056
return React.useMemo(
1050-
() => ({
1051-
async revalidate() {
1052-
await dataRouterContext.router.revalidate();
1053-
},
1054-
state: state.revalidation,
1055-
}),
1056-
[dataRouterContext.router, state.revalidation]
1057+
() => ({ revalidate, state: state.revalidation }),
1058+
[revalidate, state.revalidation]
10571059
);
10581060
}
10591061

0 commit comments

Comments
 (0)