Skip to main content
All posts
react frontend javascript

Building with React in 2026

A practical look at how I use React today: server components, composable patterns, and when to reach for something else entirely.

5 min read

React has changed enormously over the past few years. Server Components, the use hook, compiler optimisations in React 19 — it can be hard to know what “idiomatic React” even means anymore. Here’s how I think about building with it in 2026.

Server Components First

The mental model shift that’s taken me longest to internalise: reach for a Server Component first, and only opt into a Client Component when you have a concrete reason. The concrete reasons are: interactivity (event handlers), browser APIs, or React hooks.

// ✅ Default: Server Component — no 'use client', no JS shipped
export default async function ProjectList() {
  const projects = await db.query.projects.findMany();
  return (
    <ul>
      {projects.map(p => <ProjectCard key={p.id} project={p} />)}
    </ul>
  );
}

Most of the work — data fetching, layout, content rendering — can and should happen on the server.

Composable Patterns Over Prop Drilling

When building UI, I now reach for the Compound Component pattern much earlier than I used to. Instead of accumulating boolean props on a single component, I design a small tree of composable parts.

// Instead of <Card header="…" footer="…" hasBorder showShadow>
<Card>
  <Card.Header>…</Card.Header>
  <Card.Body>…</Card.Body>
  <Card.Footer>…</Card.Footer>
</Card>

This keeps individual components simple and makes the call sites readable.

When to Reach for Something Else

React isn’t always the answer. For this portfolio site I used Astro — because most of what I’m rendering is static content. Shipping React’s runtime to display a blog post is overkill.

The rule I’ve landed on: use React when your UI has meaningful state and interaction. Use something lighter (Astro, plain HTML, a web component) when it doesn’t.

React 19 and the Compiler

React 19’s compiler automatically adds memoisation where needed, removing most of the manual useMemo/useCallback calls that used to litter codebases. In practice this means fewer bugs from stale closures and less cognitive overhead.

I’ve been running it in opt-in mode on a production Next.js app at Bekk for a few months. The results are positive — measurable render count reductions in components that deal with large data tables, with zero changes to application code.


React in 2026 is mature and well-suited for complex interactive UIs. The trick is knowing when not to use it. Start with the server, add interactivity intentionally, and lean on composition over configuration.