Skip to content

Commit 6c36c87

Browse files
authored
Allow redirects to be returned from client side middleware (#14598)
1 parent 1c6634e commit 6c36c87

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed
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+
Allow redirects to be returned from client side middleware

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

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,110 @@ describe("context/middleware", () => {
16841684
});
16851685
});
16861686
});
1687+
1688+
describe("redirects", () => {
1689+
it("allows you to return redirects before next from client middleware", async () => {
1690+
router = createRouter({
1691+
history: createMemoryHistory(),
1692+
routes: [
1693+
{
1694+
path: "/",
1695+
},
1696+
{
1697+
path: "/redirect",
1698+
middleware: [
1699+
async () => {
1700+
return redirect("/target");
1701+
},
1702+
],
1703+
},
1704+
{
1705+
path: "/target",
1706+
},
1707+
],
1708+
});
1709+
1710+
await router.navigate("/redirect");
1711+
expect(router.state.location.pathname).toBe("/target");
1712+
});
1713+
1714+
it("allows you to return redirects after next from client middleware", async () => {
1715+
router = createRouter({
1716+
history: createMemoryHistory(),
1717+
routes: [
1718+
{
1719+
path: "/",
1720+
},
1721+
{
1722+
path: "/redirect",
1723+
middleware: [
1724+
async (_, next) => {
1725+
await next();
1726+
return redirect("/target");
1727+
},
1728+
],
1729+
},
1730+
{
1731+
path: "/target",
1732+
},
1733+
],
1734+
});
1735+
1736+
await router.navigate("/redirect");
1737+
expect(router.state.location.pathname).toBe("/target");
1738+
});
1739+
1740+
it("allows you to throw redirects before next from client middleware", async () => {
1741+
router = createRouter({
1742+
history: createMemoryHistory(),
1743+
routes: [
1744+
{
1745+
path: "/",
1746+
},
1747+
{
1748+
path: "/redirect",
1749+
middleware: [
1750+
async () => {
1751+
throw redirect("/target");
1752+
},
1753+
],
1754+
},
1755+
{
1756+
path: "/target",
1757+
},
1758+
],
1759+
});
1760+
1761+
await router.navigate("/redirect");
1762+
expect(router.state.location.pathname).toBe("/target");
1763+
});
1764+
1765+
it("allows you to throw redirects after next from client middleware", async () => {
1766+
router = createRouter({
1767+
history: createMemoryHistory(),
1768+
routes: [
1769+
{
1770+
path: "/",
1771+
},
1772+
{
1773+
path: "/redirect",
1774+
middleware: [
1775+
async (_, next) => {
1776+
await next();
1777+
throw redirect("/target");
1778+
},
1779+
],
1780+
},
1781+
{
1782+
path: "/target",
1783+
},
1784+
],
1785+
});
1786+
1787+
await router.navigate("/redirect");
1788+
expect(router.state.location.pathname).toBe("/target");
1789+
});
1790+
});
16871791
});
16881792

16891793
describe("middleware - handler.query", () => {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5664,7 +5664,13 @@ function runClientMiddlewarePipeline(
56645664
return runMiddlewarePipeline(
56655665
args,
56665666
handler,
5667-
(r) => r, // No post-processing needed on the client
5667+
(r) => {
5668+
// Throw any redirect responses to short circuit
5669+
if (isRedirectResponse(r)) {
5670+
throw r;
5671+
}
5672+
return r;
5673+
},
56685674
isDataStrategyResults,
56695675
errorHandler,
56705676
);

0 commit comments

Comments
 (0)