Skip to content

Commit 677888d

Browse files
committed
rsc post refinements
1 parent 9a5ac54 commit 677888d

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

src/blog/composite-components.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ Your client code opts into interactivity with `'use client'`. **Composition flow
1515

1616
What if it didn't have to?
1717

18-
What if RSCs were actually components? **Fetchable. Cacheable. Composable by the client.** Primitives that flow through your router, your cache, your data layer, without special directives or framework lock-in.
18+
What if RSCs were actually components? **Fetchable. Cacheable. Composable by the client.** Primitives that flow through your router, your cache, your data layer. No new directives beyond React's standard `'use client'`. A wire format that's standard Flight.
1919

2020
That's what we built in **TanStack Start**.
2121

22+
> **Status:** RSC support ships as an experimental feature in TanStack Start RC and will remain experimental into early v1. The API design is stable but expect refinements. See the [Start documentation](https://tanstack.com/start) for setup instructions.
23+
2224
---
2325

2426
## Why RSCs Matter
@@ -39,15 +41,11 @@ RSCs aren't about replacing client interactivity. They're about choosing where w
3941

4042
## The One-Way Problem
4143

42-
In existing RSC implementations, the server is the only place that decides what interactive elements to render.
43-
44-
Need a `<Link>` with prefetching? **Server** renders it with `'use client'`.
45-
Need a dashboard widget? Server renders the boundary, marks it client. **The server is always the decision-maker. The client is always the recipient.**
44+
Existing RSC implementations support interleaving server and client components. You can pass `children` from a client component into a server component. Next.js documents this pattern explicitly. That works.
4645

47-
This works. **But it's also limiting.**
46+
But the server still produces the final RSC tree on each navigation. The client receives a server-owned tree wholesale. It can't independently request server-rendered subtrees and compose them based on client state. It can't cache a server component and reuse it across navigations. It can't fetch two server components and interleave them in a client-defined layout.
4847

49-
What if the server wants to render some interactive elements directly (like `<Link>`) but also **defer entire regions of interactivity back to the client**?
50-
In the traditional model, you'd create a new client component, a new file, a new boundary. **Every deferral is a seam.**
48+
**Next supports slotting, but the server still produces the final tree per request. What if RSC output were first-class data that the client could request, cache, and compose?**
5149

5250
---
5351

@@ -156,6 +154,8 @@ When `createServerFn` returns a server component, that component is a **stream**
156154

157155
This works for SSR (streaming HTML during initial page load) and for client-side fetches (streaming RSC payloads during navigation or data refetches).
158156

157+
The examples in this post await data before creating the component for simplicity. In practice, you can await inside the component body with nested `<Suspense>` boundaries to stream UI progressively as each piece resolves.
158+
159159
Streams are universal. They work with:
160160

161161
- **TanStack Router** → Load server components in route loaders, stream them during navigation
@@ -191,7 +191,7 @@ const { data: Layout } = useQuery({
191191
})
192192
```
193193

194-
**The server component is just data.** Fetch it, cache it, transform it, compose it. **No special APIs. No framework-specific caching layers.** Just streams flowing through tools you already know.
194+
**The server component is just data.** Fetch it, cache it, compose it. **No special APIs. No framework-specific caching layers.** Just streams flowing through tools you already know.
195195

196196
---
197197

@@ -205,6 +205,8 @@ Every property access and function call is tracked:
205205

206206
You can destructure props normally. `({ children, renderActions })` works just as well as `props.children`. The proxy handles both patterns.
207207

208+
**A few rules apply:** Slot placeholders are opaque on the server. You can't `Object.keys()` the props proxy and expect to enumerate what was passed (you'll get nothing useful). You can't `JSON.stringify()` a render prop. Calls to render props are recorded in invocation order and replayed on the client in the same order. The [documentation](/start/latest/docs/server-components) covers the full contract.
209+
208210
**Over the wire, it's a React element stream** with embedded placeholders. On the client:
209211

210212
1. The stream decodes into a React element tree
@@ -221,7 +223,7 @@ props.renderActions({ renderActions prop is called
221223
with full hooks/state/context
222224
```
223225

224-
**Type safety flows through automatically.** The function signature on the server determines what arguments your client function receives:
226+
**Type safety flows through in TypeScript when client and server share types.** The function signature on the server determines what arguments your client function receives:
225227

226228
```tsx
227229
const getPost = createServerFn().handler(async ({ data }) => {
@@ -265,7 +267,7 @@ You choose patterns **per-route, per-component, per-use-case**. The architecture
265267

266268
## Current Status: Experimental
267269

268-
This is the first experimental release of RSCs in TanStack Start. A few things to know:
270+
RSC support ships as an experimental feature in TanStack Start RC and will remain experimental into early v1. A few things to know:
269271

270272
**React's Flight serializer**: This release uses React's native RSC Flight protocol for serialization. That means TanStack Start's usual serialization features aren't available within server components for now. Standard JavaScript primitives, Dates, and React elements serialize fine. Custom serialization plugins and extended types will come in a future release as we unify the serialization layers.
271273

@@ -336,11 +338,15 @@ Not currently. Server functions that return UI must wrap it in `createServerComp
336338

337339
**React Context**: Context providers rendered by the server component _will_ wrap client children. If your server component renders `<ThemeProvider value="dark">{children}</ThemeProvider>`, the client children can consume that context. However, the context must be defined in a way that works across the server/client boundary (typically with `'use client'` on the provider component).
338340

341+
### Any security considerations?
342+
343+
RSC endpoints accept and emit serialized payloads, so treat them like any API surface: authenticate requests, validate inputs, and keep React patched. Recent React advisories have touched RSC and server function serialization, so staying current matters.
344+
339345
---
340346

341347
## Get Started
342348

343-
TanStack Start's RSC model is available now in experimental.
349+
TanStack Start's RSC model is available now as an experimental feature.
344350

345351
- [Documentation](https://tanstack.com/start)
346352
- [GitHub](https://github.com/tanstack/router)

0 commit comments

Comments
 (0)