This document describes React Router's integration with React Server Components (RSC), an experimental feature that enables server-side rendering of React components in a separate environment from client code. This covers the server-side request matching and payload generation, client-side hydration and navigation, and the communication protocol between server and client.
For information about standard server-side rendering without RSC, see sections 4.1 and 4.2. For middleware integration, see 3.5.
Status: RSC support is experimental and subject to breaking changes in minor/patch releases.
React Router's RSC implementation provides a complete solution for server components, including request routing, payload serialization, client hydration, and navigation. The system operates in both Framework Mode and Data Mode, with slight API differences between them.
Sources: packages/react-router/lib/rsc/server.rsc.ts1-900 packages/react-router/lib/rsc/server.ssr.tsx1-400 packages/react-router/lib/rsc/browser.tsx1-800
The matchRSCServerRequest function handles incoming requests and routes them to the appropriate handlers. It operates in two modes: document requests and data requests.
Key Functions:
| Function | Location | Purpose |
|---|---|---|
matchRSCServerRequest | server.rsc.ts700-900 | Main entry point for RSC request handling |
handleAction | server.rsc.ts450-550 | Executes server actions and manages redirects |
handleLoaders | server.rsc.ts550-650 | Runs loader functions for matched routes |
encodeRSCPayload | server.rsc.ts850-900 | Serializes payload to ReadableStream |
Sources: packages/react-router/lib/rsc/server.rsc.ts700-900 docs/api/rsc/matchRSCServerRequest.md1-100
The routeRSCServerRequest function integrates RSC with traditional SSR, handling both HTML rendering and data requests:
Integration Points:
createFromReadableStream (server.ssr.tsx38-40)renderHTMLToReadableStream (server.ssr.tsx100-150)Sources: packages/react-router/lib/rsc/server.ssr.tsx1-400 docs/api/rsc/routeRSCServerRequest.md1-80
React Router defines four distinct payload types for different response scenarios:
Payload Type Details:
| Type | Purpose | Key Fields | Usage |
|---|---|---|---|
RSCRenderPayload | Full page render | matches, loaderData, errors, patches | Initial page load, navigation |
RSCManifestPayload | Route discovery | patches | Fog-of-war route loading |
RSCActionPayload | Server action result | actionResult, rerender | Form submissions, server actions |
RSCRedirectPayload | Navigation redirect | location, status, replace | Server-initiated redirects |
Sources: packages/react-router/lib/rsc/server.rsc.ts228-277
The RSCRouteManifest describes route metadata for client-side routing:
Sources: packages/react-router/lib/rsc/server.rsc.ts202-221
The RSCHydratedRouter component manages client-side routing with RSC payloads:
Initialization Flow:
getPayload() to decode initial RSC payload from SSR (browser.tsx200-250)DataRouteObject[] from RSCRouteManifest[] (browser.tsx250-300)getRSCDataStrategy() (browser.tsx400-500)Sources: packages/react-router/lib/rsc/browser.tsx150-500 docs/api/rsc/RSCHydratedRouter.md1-100
The RSC data strategy handles navigation and data fetching differently from standard single-fetch:
Key Differences from Standard Single Fetch:
| Aspect | Standard Single Fetch | RSC Single Fetch |
|---|---|---|
| URL Extension | .data | .rsc |
| Encoding | Turbo-stream | React Flight |
| Server Actions | Regular POST | callServer() with encoding |
| Components | Client-only | Server + Client components |
| Streaming | Turbo-stream decoder | createFromReadableStream |
Sources: packages/react-router/lib/rsc/browser.tsx500-800 packages/react-router/lib/dom/ssr/single-fetch.tsx178-297
Server actions allow client components to call server-side functions directly:
Server Action Context:
The AsyncLocalStorage context tracks whether an action is currently executing, allowing the redirect(), redirectDocument(), and replace() functions to capture redirects and store them for later processing (server.rsc.ts79-122).
Action Handler Flow:
decodeAction(formData) deserializes arguments (server.rsc.ts480-500)AsyncLocalStorage context (server.rsc.ts500-530)redirect(), stored in context (server.rsc.ts91-99)Sources: packages/react-router/lib/rsc/server.rsc.ts79-550 packages/react-router/lib/rsc/browser.tsx100-200
The createCallServer function creates the React callServer implementation:
Action ID Management:
Each server action call increments window.__routerActionID to provide unique identifiers for tracking and debugging (browser.tsx120-150).
Sources: packages/react-router/lib/rsc/browser.tsx67-200 docs/api/rsc/createCallServer.md1-80
RSC error handling uses a specialized error boundary structure:
Error Flow:
ErrorBoundary catches and renders error UI (errorBoundaries.tsx1-100)Special Error Types:
Sources: packages/react-router/lib/rsc/server.rsc.ts300-350 packages/react-router/lib/errors.ts67-90 packages/react-router/lib/rsc/errorBoundaries.tsx1-100
RSC supports lazy route discovery through manifest requests:
Manifest Request Parameters:
paths: Comma-separated list of paths to fetch routes forPatch Processing:
RSCManifestPayload contains route metadata (server.rsc.ts245-249)patchRoutesOnNavigation adds routes to router (browser.tsx750-800)Sources: packages/react-router/lib/rsc/server.rsc.ts650-700 packages/react-router/lib/rsc/browser.tsx700-800
RSC routes support middleware in a similar way to standard routes, with some limitations:
Middleware Execution Context:
AsyncLocalStorage context as actionsSources: packages/react-router/lib/rsc/server.rsc.ts400-450 docs/how-to/middleware.md1-100
RSC uses a modified version of the single fetch protocol:
| Feature | Standard | RSC |
|---|---|---|
| URL pattern | path.data | path.rsc |
| Response type | text/x-script | text/x-component |
| Encoding | Turbo-stream | React Flight |
| Actions | Form encoding | encodeReply() |
| Server functions | Not supported | Supported via callServer |
Shared Concepts:
_routes parameter for selective loader executionshouldRevalidatedata() response helperSources: packages/react-router/lib/rsc/browser.tsx500-600 packages/react-router/lib/dom/ssr/single-fetch.tsx612-649
RSC routes use RSCRouteConfigEntry type:
Key Configuration Points:
Component: Server component (default export from route module)lazy: Dynamic import for code splittingclientAction/clientLoader: Client-side overrides (if needed)ErrorBoundary: Must be client component (marked with "use client")Sources: packages/react-router/lib/rsc/server.rsc.ts159-198
RSC requires bundler-specific implementations:
| Function | Location | Purpose |
|---|---|---|
createFromReadableStream | Bundler-specific | Decode RSC payloads |
encodeReply | Bundler-specific | Serialize server action args |
createTemporaryReferenceSet | Bundler-specific | Track references during encoding |
decodeReply | Server-side | Deserialize action arguments |
Example Integration:
Sources: packages/react-router/lib/rsc/server.ssr.tsx36-100 integration/helpers/rsc-vite/src/entry.ssr.tsx1-50
Refresh this wiki