·6 min read

React Server Components in 2026: from experiment to default

Where RSC lands in 2026: what changed, what I actually use day to day, where it still hurts, and how I’d start a new project today.

ReactNext.jsPerformance

React Server Components have been the most-discussed frontend topic of the last three years, and in 2026 they finally feel like a normal tool rather than an experiment. Next.js App Router pushed them mainstream, the React team shipped a stable streaming RSC payload, and a meaningful number of frameworks, Remix, TanStack Start, Waku, now treat RSC as a first-class building block instead of a Next.js peculiarity.

What actually changed

The shift is less about a new API and more about a new default. A component is now assumed to be a server component unless it opts in to the client. "use client" is the boundary that matters, and getting that boundary right is what separates fast apps from slow ones. Server components run on the server, never ship their JavaScript, and can talk directly to your data layer. Client components ship to the browser, handle interactivity, and own state.

The mental model that works for me is to treat the server component tree as a render-time configuration of the page, and client components as small islands of interactivity inside it. A product page is a server component. The add-to-cart button inside it is a client component. Everything around the button, image gallery, breadcrumb, description, reviews, stays on the server.

What I’ve been using day to day

  • Server actions for form submissions instead of handwritten API routes. They co-locate the mutation with the component and remove a category of glue code. Just remember they’re POST requests and you still need CSRF discipline.
  • Streaming with <Suspense> boundaries around anything slow. Time-to-first-byte gets to ship the layout and shell first, and the data-heavy bits stream in afterwards. This is where RSC pays its weight.
  • Data fetching at the leaf. Instead of fetching at the page level and prop-drilling, each server component fetches what it actually needs. React deduplicates with the request cache, so you can stop pretending you have to centralise data fetching.

Where it still hurts

Three pain points remain. First, the client-server boundary is load-bearing for performance, and getting it wrong is surprisingly easy. A small "use client" in the wrong place pulls a much bigger subtree into the browser bundle. Run a bundle analyser every few weeks.

Second, third-party libraries still assume client-side React. If a library uses context or hooks at the top level of its public API, it forces every consumer to be a client component. Wrapping it in a small client adapter is the workaround, and most well-maintained libraries now ship those adapters themselves.

Third, the developer experience around server-only code is still finding its shape. Linting can catch the obvious cases, using browser APIs in a server component, but the subtler ones (passing non-serialisable props across the boundary, accidentally bundling secrets) require deliberate review.

If you’re starting a new project in 2026

Default to server components. Reach for "use client" only when you have state, effects, browser APIs, or event handlers that depend on the DOM. Co-locate data fetching with the component that renders the data. Use Suspense liberally. Treat your bundle size as a feature you maintain, not a side effect you measure once.

The web finally has a model where the default page is fast, the default bundle is small, and interactivity is something you add deliberately rather than fight for. That’s the headline. Everything else is detail.