Skip to content

Commit 0163df4

Browse files
authored
fix(react-router): run action handlers for routes with middleware even if no loader is present (#14443)
1 parent 2b76433 commit 0163df4

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

.changeset/nice-donuts-obey.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+
Ensure action handlers run for routes with middleware even if no loader is present

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,71 @@ describe("context/middleware", () => {
477477
]);
478478
});
479479

480+
it("runs middleware even if no loader exists but an action is present", async () => {
481+
let snapshot;
482+
router = createRouter({
483+
history: createMemoryHistory(),
484+
routes: [
485+
{
486+
path: "/",
487+
},
488+
{
489+
id: "parent",
490+
path: "/parent",
491+
middleware: [
492+
async ({ context }, next) => {
493+
await next();
494+
// Grab a snapshot at the end of the upwards middleware chain
495+
snapshot = context.get(orderContext);
496+
},
497+
getOrderMiddleware(orderContext, "a"),
498+
getOrderMiddleware(orderContext, "b"),
499+
],
500+
children: [
501+
{
502+
id: "child",
503+
path: "child",
504+
middleware: [
505+
getOrderMiddleware(orderContext, "c"),
506+
getOrderMiddleware(orderContext, "d"),
507+
],
508+
action({ context }) {
509+
context.get(orderContext).push("child action");
510+
},
511+
},
512+
],
513+
},
514+
],
515+
});
516+
517+
await router.navigate("/parent/child", {
518+
formMethod: "post",
519+
formData: createFormData({}),
520+
});
521+
522+
expect(snapshot).toEqual([
523+
// Action
524+
"a middleware - before next()",
525+
"b middleware - before next()",
526+
"c middleware - before next()",
527+
"d middleware - before next()",
528+
"child action",
529+
"d middleware - after next()",
530+
"c middleware - after next()",
531+
"b middleware - after next()",
532+
"a middleware - after next()",
533+
// Revalidation
534+
"a middleware - before next()",
535+
"b middleware - before next()",
536+
"c middleware - before next()",
537+
"d middleware - before next()",
538+
"d middleware - after next()",
539+
"c middleware - after next()",
540+
"b middleware - after next()",
541+
"a middleware - after next()",
542+
]);
543+
});
544+
480545
it("returns result of middleware in client side routers", async () => {
481546
let values: unknown[] = [];
482547
let consoleSpy = jest

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5827,13 +5827,16 @@ function getDataStrategyMatch(
58275827
!isMutationMethod(request.method) &&
58285828
(lazy || loader));
58295829

5830-
// If this match was marked `shouldLoad` due to a middleware and it
5831-
// doesn't have a `loader` to run and no `lazy` to add one, then we can
5832-
// just return undefined from the "loader" here
5830+
// For GET requests, if this match was marked `shouldLoad` due to a
5831+
// middleware and it doesn't have a `loader` to run and no `lazy` to add
5832+
// one, then we can just return undefined from the "loader" here
58335833
let isMiddlewareOnlyRoute =
58345834
middleware && middleware.length > 0 && !loader && !lazy;
58355835

5836-
if (callHandler && !isMiddlewareOnlyRoute) {
5836+
if (
5837+
callHandler &&
5838+
(isMutationMethod(request.method) || !isMiddlewareOnlyRoute)
5839+
) {
58375840
return callLoaderOrAction({
58385841
request,
58395842
unstable_pattern,

0 commit comments

Comments
 (0)