If you stopped reading React release notes after hooks landed, here's the short version of where we are in mid-2026: React 19 is the new baseline, the React Compiler has shipped, and most of what we used to teach junior engineers about useMemo and useCallback is now actively wrong. The mental model has changed, not just the API surface.
This is a tour of what's actually trending — what we are using on production projects at Techglock, what we have stopped using, and what is genuinely worth the migration effort right now.
React 19 Is the New Default — Stop Targeting 18
React 19 went GA in late 2024. By mid-2026 it is universal in greenfield work and the default in every major starter (Next.js, Remix, TanStack Start, Vite). Anything you can do in 18 you can still do in 19, but several patterns are now strictly better:
- Actions and
useActionState— server-side form mutations no longer need a custom handler, a loading boolean, and an error state wired by hand. The hook gives you all three. useOptimistic— optimistic UI without a state library. You declare the optimistic value next to the real value and React handles the rollback if the action fails.useFormStatus— submit buttons that know whether their parent form is pending, without prop drilling.- The
use()hook — read a promise or context inline. Combined with Suspense, this kills a lot ofuseEffect+useStatedata-fetching boilerplate. - Document metadata in JSX —
<title>,<meta>,<link>elements are hoisted automatically.react-helmetis no longer needed.
If you are still writing const [pending, setPending] = useState(false) around every form submit, you are doing it the old way. The new way is shorter, more correct, and integrates with Suspense for streaming.
The React Compiler Killed Manual Memoization
This is the biggest mental shift of 2026. The React Compiler (the project formerly known as React Forget) reached stable in early 2025 and is now the default in Next.js and most starters. It analyses your component tree at build time and inserts memoization automatically — at the granularity of individual JSX expressions, not whole components.
What this means in practice:
- You no longer need
useMemofor expensive computations in component bodies. The compiler caches them. - You no longer need
useCallbackfor stable function identity. The compiler stabilises closures automatically. - You no longer need
React.memoon most leaf components. The compiler memoises child renders based on actual prop equality.
The old advice — "wrap callbacks in useCallback when passing them to memoised children" — is now actively wrong. Manual memoisation interferes with the compiler's analysis and can produce worse output than letting it work. On every greenfield project we have audited in the last six months, removing manual memoisation hooks made the bundle smaller and the runtime faster.
The new rule: write components naively, let the compiler optimise. Reach for useMemo only when you genuinely need referential equality for an external API (a stable key for an IntersectionObserver, for instance).
Server Components Are Now Genuinely Useful
React Server Components (RSCs) were technically shipped in 2023, but in mid-2026 they are finally being used the way they were designed. Three things changed:
- Next.js 15+ stabilised the bundling story (Turbopack handles the boundary cleanly).
- The
"use cache"directive lets you cache server component output per-arguments — a much better mental model than the per-fetch caching of Next.js 13/14. - Streaming with Suspense became reliable across CDNs and the React DevTools.
What this changes for product engineers: most data fetching now happens in async server components without a hook in sight. useEffect(() => fetch(...)) is fading from the codebase. You write:
async function ProductPage({ id }: { id: string }) {
const product = await db.products.find(id);
return <ProductDetail data={product} />;
}
That entire pattern — top-level await, no client-side loading state, no useState, no waterfall — is now standard. Client components are reserved for actual interactivity: forms, animations, anything that listens to a DOM event.
State Management Has Quietly Shrunk
Redux is not dead, but it is over-engineered for almost every app we touch in 2026. Server components took over data fetching. Server actions took over mutations. URL state (via Next.js or TanStack Router) took over filters and pagination. What's left for a client store is genuinely small — and Zustand, Jotai, or Valtio handle it in 20 lines.
The shape of a modern React app:
- Server state — lives on the server, fetched in server components, cached with
"use cache"or TanStack Query for client-fetched cases. - URL state — filters, search, sort, pagination.
nuqsor framework primitives. - Form state — local to the form, managed by
useActionStateor React Hook Form for complex cases. - UI state — modals, drawers, tabs.
useStatein the closest common parent.
If you find yourself reaching for a global store, ask which of the four buckets above it actually belongs to. Eight times out of ten, the answer is "URL" or "form".
Styling: Tailwind 4 Is the Default; CSS-in-JS Is Fading
Tailwind 4 shipped in early 2025 with a Rust-based engine, no PostCSS pipeline required, and significantly smaller production CSS. By mid-2026 it is the default styling layer in essentially every greenfield React project we ship. CSS-in-JS libraries — Emotion, styled-components — have shrunk to legacy maintenance. They don't work well with Server Components (you can't run them on the server without a runtime), which alone is enough to retire them from new work.
For component primitives, shadcn/ui plus Radix has eaten most of the ecosystem. We start every UI from there and customise. Headless UI is still a fine choice if you are deep in the Tailwind Labs orbit, but shadcn's "copy the code into your repo" model has clearly won for the agency / product-team workflow.
TanStack Is Eating React Router's Lunch
React Router is fine. TanStack Router is better, especially if you want type-safe routing, search-param validation, and built-in code splitting that actually works without ceremony. By mid-2026, TanStack Router and the new TanStack Start meta-framework have a real share of greenfield SPA projects that don't need server components.
For projects that do need server components, Next.js still leads — but TanStack Start is the first credible alternative that isn't Remix (which is now React Router itself). If you have been ignoring TanStack as a "developer hobby project", look again. The router alone is worth the migration.
The Testing Story Finally Settled
By mid-2026 the testing stack we recommend is:
- Vitest for unit and component tests. Jest is still around in legacy codebases but new projects skip it.
- Testing Library for component assertions. No change here — it remains correct.
- Playwright for end-to-end and visual regression. Cypress lost mindshare and Playwright's parallelism is just better.
- MSW (Mock Service Worker) for API mocking in tests and in dev. Still the cleanest way to mock at the network layer.
The one we keep removing from inherited codebases: Storybook, unless the team is actually using it. Most teams don't, and the build cost outweighs the value. shadcn/ui plus a /playground route inside the app gives us 80 percent of Storybook's benefit at 5 percent of the maintenance cost.
What We Have Stopped Using
For honesty, here is the kill list — patterns that were standard in 2023 and that we no longer write in 2026:
- Manual
useMemo/useCallback/React.memofor performance. The compiler handles it. useEffectfor data fetching. Server components or TanStack Query handle it.useStatefor form submission state.useActionStatehandles it.- Redux for new projects. Server state + URL state + small Zustand store handles it.
- Styled-components / Emotion for new projects. Tailwind 4 handles it.
- Class components. React Server Components don't even support them, and that's fine.
- PropTypes. TypeScript handles it. (This one should have died in 2020 and yet.)
The Migration Order If You're Catching Up
For teams that froze their React knowledge at 18, here is the priority order we use when modernising client codebases:
- Upgrade to React 19 — it's a drop-in upgrade for most apps. The compatibility surface is good.
- Enable the React Compiler — opt-in is per-file via a directive. Start with leaf components and work upward.
- Convert form handlers to
useActionState— biggest immediate developer-experience win. - Migrate to Tailwind 4 if you are on a CSS-in-JS library that doesn't support server components.
- Adopt server components for new pages first; convert existing ones case by case.
- Audit and remove manual memoisation after the compiler has been on for a few weeks.
None of these are "rewrite everything" migrations. They are incremental. The hardest part is the mental shift — accepting that React 19 wants you to write less code, not more.
What's Coming Next
Three things to watch through the back half of 2026:
- React Server Functions getting first-class support outside Next.js. TanStack Start is already there; Astro and others are catching up.
- Streaming SSR for static-host targets. The current story is good for Vercel and other Node runtimes; static hosts are catching up via edge functions.
- The "directives" pattern becoming standard.
"use server","use client","use cache","use memo"— the directive-based contract between framework and component is shaping up as React's universal protocol.
If you only do one thing after reading this: turn on the React Compiler in one file, delete every useMemo and useCallback in that file, and run your tests. The change in how the codebase feels will tell you everything else you need to know about where React is going in 2026.