diff --git a/.changeset/plenty-olives-rush.md b/.changeset/plenty-olives-rush.md new file mode 100644 index 0000000000..1299950ae9 --- /dev/null +++ b/.changeset/plenty-olives-rush.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +add RSC unstable_getRequest diff --git a/integration/rsc/rsc-test.ts b/integration/rsc/rsc-test.ts index 974150ad1d..9ae43b4288 100644 --- a/integration/rsc/rsc-test.ts +++ b/integration/rsc/rsc-test.ts @@ -545,7 +545,12 @@ implementations.forEach((implementation) => { id: "render-route-error-response", path: "render-route-error-response/:id?", lazy: () => import("./routes/render-route-error-response/home"), - } + }, + { + id: "get-request", + path: "/get-request", + lazy: () => import("./routes/get-request/get-request"), + }, ], }, ] satisfies RSCRouteConfig; @@ -1549,6 +1554,17 @@ implementations.forEach((implementation) => { return
Oh no D:
; } `, + + "src/routes/get-request/get-request.tsx": js` + import { unstable_getRequest as getRequest } from "react-router"; + + export function action() { return null; } + + export default function GetRequest() { + const request = getRequest(); + return{request.method}
; + } + `, }, }); }); @@ -1892,6 +1908,20 @@ implementations.forEach((implementation) => { ); await expect(page.getByText("400 Oh no! Test")).toBeAttached(); }); + + test("Supports getRequest in server components", async ({ page }) => { + await page.goto(`http://localhost:${port}/get-request`); + await expect(page.getByText("GET")).toBeAttached(); + + const response = await page.request.fetch( + `http://localhost:${port}/get-request`, + { + method: "POST", + }, + ); + const body = await response.text(); + expect(body).toContain("POST
"); + }); }); test.describe("Server Actions", () => { diff --git a/packages/react-router/index-react-server.ts b/packages/react-router/index-react-server.ts index 9f880056b4..b7e5b9c03e 100644 --- a/packages/react-router/index-react-server.ts +++ b/packages/react-router/index-react-server.ts @@ -1,5 +1,8 @@ // RSC APIs -export { matchRSCServerRequest as unstable_matchRSCServerRequest } from "./lib/rsc/server.rsc"; +export { + getRequest as unstable_getRequest, + matchRSCServerRequest as unstable_matchRSCServerRequest, +} from "./lib/rsc/server.rsc"; export type { DecodeActionFunction as unstable_DecodeActionFunction, diff --git a/packages/react-router/index.ts b/packages/react-router/index.ts index 17ac647117..696362f091 100644 --- a/packages/react-router/index.ts +++ b/packages/react-router/index.ts @@ -316,7 +316,8 @@ export { export { RSCDefaultRootErrorBoundary as UNSAFE_RSCDefaultRootErrorBoundary } from "./lib/rsc/errorBoundaries"; // Re-export of RSC types -import type { matchRSCServerRequest } from "./lib/rsc/server.rsc"; +import type { getRequest, matchRSCServerRequest } from "./lib/rsc/server.rsc"; +export declare const unstable_getRequest: typeof getRequest; export declare const unstable_matchRSCServerRequest: typeof matchRSCServerRequest; export type { diff --git a/packages/react-router/lib/rsc/server.rsc.ts b/packages/react-router/lib/rsc/server.rsc.ts index 0c9e1e66da..e19c12326d 100644 --- a/packages/react-router/lib/rsc/server.rsc.ts +++ b/packages/react-router/lib/rsc/server.rsc.ts @@ -78,6 +78,7 @@ const WithHydrateFallbackProps: typeof WithHydrateFallbackPropsType = type ServerContext = { redirect?: Response; + request: Request; runningAction: boolean; }; @@ -88,6 +89,16 @@ const globalVar = (typeof globalThis !== "undefined" ? globalThis : global) as { const ServerStorage = (globalVar.___reactRouterServerStorage___ ??= new AsyncLocalStorage