Skip to content

Commit 01243a2

Browse files
authored
Fix middleware on initial load without loaders (#14393)
1 parent eb61a29 commit 01243a2

File tree

3 files changed

+73
-3
lines changed

3 files changed

+73
-3
lines changed

.changeset/twelve-dogs-pump.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+
Fix Data Mode regression causing a 404 during initial load in when `middleware` exists without any `loader` functions

packages/react-router/__tests__/router/context-middleware-test.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,62 @@ describe("context/middleware", () => {
300300
]);
301301
});
302302

303+
it("runs middleware on initialization even if no loaders exist", async () => {
304+
let snapshot;
305+
router = createRouter({
306+
history: createMemoryHistory(),
307+
routes: [
308+
{
309+
path: "/",
310+
middleware: [
311+
async ({ context }, next) => {
312+
await next();
313+
// Grab a snapshot at the end of the upwards middleware chain
314+
snapshot = context.get(orderContext);
315+
},
316+
getOrderMiddleware(orderContext, "a"),
317+
getOrderMiddleware(orderContext, "b"),
318+
],
319+
children: [
320+
{
321+
index: true,
322+
middleware: [
323+
getOrderMiddleware(orderContext, "c"),
324+
getOrderMiddleware(orderContext, "d"),
325+
],
326+
},
327+
],
328+
},
329+
],
330+
});
331+
let initPromise = new Promise((r) => {
332+
let unsub = router.subscribe((state) => {
333+
if (state.initialized) {
334+
unsub();
335+
r(undefined);
336+
}
337+
});
338+
});
339+
await router.initialize();
340+
await initPromise;
341+
expect(router.state).toMatchObject({
342+
initialized: true,
343+
location: { pathname: "/" },
344+
navigation: { state: "idle" },
345+
errors: null,
346+
});
347+
expect(snapshot).toEqual([
348+
"a middleware - before next()",
349+
"b middleware - before next()",
350+
"c middleware - before next()",
351+
"d middleware - before next()",
352+
"d middleware - after next()",
353+
"c middleware - after next()",
354+
"b middleware - after next()",
355+
"a middleware - after next()",
356+
]);
357+
});
358+
303359
it("runs middleware even if no loaders exist", async () => {
304360
let snapshot;
305361
router = createRouter({

packages/react-router/lib/router/router.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5744,13 +5744,22 @@ function getDataStrategyMatch(
57445744
return shouldRevalidateLoader(match, unstable_shouldRevalidateArgs);
57455745
},
57465746
resolve(handlerOverride) {
5747-
if (
5747+
let { lazy, loader, middleware } = match.route;
5748+
5749+
let callHandler =
57485750
isUsingNewApi ||
57495751
shouldLoad ||
57505752
(handlerOverride &&
57515753
!isMutationMethod(request.method) &&
5752-
(match.route.lazy || match.route.loader))
5753-
) {
5754+
(lazy || loader));
5755+
5756+
// If this match was marked `shouldLoad` due to a middleware and it
5757+
// doesn't have a `loader` to run and no `lazy` to add one, then we can
5758+
// just return undefined from the "loader" here
5759+
let isMiddlewareOnlyRoute =
5760+
middleware && middleware.length > 0 && !loader && !lazy;
5761+
5762+
if (callHandler && !isMiddlewareOnlyRoute) {
57545763
return callLoaderOrAction({
57555764
request,
57565765
match,

0 commit comments

Comments
 (0)