Blog/Tech News & Opinions/React 19 One Year Later: What Shipped and What Didn't
POST
April 12, 2025
LAST UPDATEDApril 12, 2025

React 19 One Year Later: What Shipped and What Didn't

A comprehensive review of React 19 one year after release, covering Server Components adoption, hooks maturity, and features still missing in production.

Tags

ReactReact 19JavaScriptFrontend
React 19 One Year Later: What Shipped and What Didn't
8 min read

React 19 One Year Later: What Shipped and What Didn't

TL;DR

React 19 has been in production for over a year now. Server Components are real and working, the new hooks are genuinely useful, and Actions have simplified form handling. But the React Compiler is still not widely adopted, the Activity API remains experimental, and ecosystem adoption has been uneven. Here is an honest look at where things stand.

What's Happening

React 19 shipped in early 2024 with a list of features that promised to reshape how we build React applications. Now, with over a year of production usage, we have enough data to separate the features that delivered on their promise from those that fell short or are still catching up.

The headline features, Server Components (RSC), Actions, and new hooks like use(), useOptimistic, and useFormStatus, are stable and in production across thousands of applications. Next.js has been the primary vehicle for RSC adoption, and it works. But "it works" comes with caveats that the initial announcements did not emphasize.

Meanwhile, the React Compiler (formerly React Forget) is available but has not achieved the widespread adoption many expected. And the Activity API, which was supposed to let you pre-render offscreen content, remains experimental.

Why It Matters

React powers a massive portion of the web. When React changes its paradigm, the ripple effects hit every frontend developer, every component library, and every hiring manager writing job descriptions. React 19's shift toward server-first rendering is the biggest architectural change since hooks replaced class components.

For developers in the trenches, this matters because:

  • Your mental model needs updating. The client-server boundary is now a first-class concept in React, not something your framework handles invisibly.
  • Library choices have changed. Some popular libraries adapted quickly; others have been slow or incompatible.
  • Migration is not optional forever. React 18 will eventually stop receiving updates, and the ecosystem is moving forward.

How It Works / What's Changed

Server Components: The Reality

Server Components work. That is the good news. You can write components that execute on the server, fetch data directly, and send rendered HTML to the client without shipping JavaScript for those components. The performance benefits are real.

tsx
// This component runs on the server - zero client JS
async function ProductPage({ id }: { id: string }) {
  const product = await db.product.findUnique({ where: { id } });
  const reviews = await db.review.findMany({ where: { productId: id } });
 
  return (
    <div>
      <ProductDetails product={product} />
      <Suspense fallback={<ReviewsSkeleton />}>
        <ReviewList reviews={reviews} />
      </Suspense>
    </div>
  );
}

The less-discussed reality: RSC adoption outside of Next.js has been limited. The React team positioned Server Components as a framework-agnostic feature, but in practice, Next.js is the only mature framework that fully supports them. Remix has been working on RSC support, and Waku is an option for lighter-weight needs, but the "any framework can use RSC" promise has not materialized broadly.

The "use client" directive, while simple in concept, has caused real friction. Developers frequently hit the boundary in unexpected places. Want to use useState in a component? It needs "use client". Want to pass a function as a prop from a server component? You cannot, unless it is a Server Action. These are learnable rules, but they add cognitive overhead that the initial pitch underestimated.

The use() Hook

The use() hook lets you read promises and context in render, including conditionally. This is genuinely useful:

tsx
function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise);
 
  return <div>{user.name}</div>;
}

Combined with Suspense, this creates a clean pattern for data loading. The promise is created in a Server Component, passed down, and the client component unwraps it with use(). No useEffect for data fetching, no loading state management.

In practice, this has replaced the useEffect data-fetching pattern in new codebases. Existing codebases have been slower to migrate because refactoring from useEffect + useState to use() + Suspense requires rethinking component boundaries.

Actions and Form Handling

Actions are the quiet success story of React 19. They simplified form handling significantly:

tsx
async function createPost(formData: FormData) {
  "use server";
 
  const title = formData.get("title") as string;
  const content = formData.get("content") as string;
 
  await db.post.create({ data: { title, content } });
  revalidatePath("/posts");
}
 
function NewPostForm() {
  return (
    <form action={createPost}>
      <input name="title" required />
      <textarea name="content" required />
      <SubmitButton />
    </form>
  );
}
 
function SubmitButton() {
  const { pending } = useFormStatus();
  return <button disabled={pending}>{pending ? "Posting..." : "Post"}</button>;
}

useFormStatus and useOptimistic work well together to create responsive forms that feel instant while server processing happens in the background. This has reduced the need for client-side form libraries in many cases.

The React Compiler Story

The React Compiler was supposed to be the feature that eliminated the need to think about memoization. No more useMemo, useCallback, or React.memo because the compiler would automatically optimize re-renders.

The compiler exists and works. You can enable it today. But adoption has been slower than expected for a few reasons:

  • Build tool integration is not seamless. It works well with Next.js but requires manual configuration for other setups.
  • Edge cases exist. Code patterns that rely on referential identity in ways the compiler does not expect can break subtly.
  • The benefit is hard to measure. For well-optimized codebases, the compiler adds little. For poorly-optimized ones, it helps, but those teams are often the least likely to adopt new tooling.

What Has Not Shipped

Activity API (formerly Offscreen): This was supposed to let you pre-render content before it is visible, enabling instant tab switches and smoother transitions. It remains experimental with no clear timeline for stable release.

Asset Loading: Built-in support for preloading stylesheets, fonts, and scripts was partially delivered. The <link> and <script> hoisting works, but the full vision of React managing all asset loading is still incomplete.

My Take

React 19 is a good release that oversold itself. The features that shipped are genuinely useful. Server Components are the right direction for web applications that need performance at scale. Actions cleaned up form handling in a way that felt overdue. The new hooks solve real problems.

But the React team's communication created expectations that reality has not met. The compiler was presented as a near-term solution to memoization, and a year later most projects still use useMemo and useCallback. The "works with any framework" promise for RSC is technically true but practically misleading.

The biggest issue I see in practice is the ecosystem split. There are now two categories of React components: those that work in Server Components and those that do not. Every library maintainer has to decide whether to support both, and many have chosen the path of least resistance by adding "use client" at the top of every file.

For new projects, React 19 with Next.js is an excellent choice. The server-first model, once you internalize the mental model, leads to faster applications with less client-side JavaScript. For existing projects, the migration path is manageable but not trivial. Take it incrementally.

What This Means for You

For new projects: Use React 19 with a framework that supports RSC. Start with server components by default and add "use client" only when you need interactivity. This inverted mental model takes a week to internalize but leads to better architecture.

For existing React 18 projects: Upgrade to React 19, but do not try to adopt Server Components all at once. Start by using the new hooks (useOptimistic, useFormStatus) in your existing client components. Migrate to RSC gradually.

For library authors: If you have not updated for React 19 compatibility, you are falling behind. At minimum, test against React 19 and ensure your components work with the new ref handling (refs are now regular props, no need for forwardRef).

For the React Compiler: Try it on a non-critical project first. If it works without issues, great. If you hit edge cases, do not force it. The manual memoization patterns still work fine.

For career development: Understanding the server-client boundary in React is now a required skill. If you are interviewing for React positions, expect questions about when to use Server Components vs Client Components and how Actions work.

FAQ

Is React 19 stable for production?

Yes, React 19 is stable and widely used in production. Server Components, Actions, and new hooks like useOptimistic work reliably in Next.js and other frameworks. The core APIs have been battle-tested across large applications at Meta and throughout the ecosystem. The main consideration is not stability but ensuring your existing libraries and patterns are compatible with the new paradigms, particularly the server-client component boundary.

What React 19 features haven't shipped yet?

The Activity API (formerly Offscreen) and some advanced compiler optimizations are still experimental and not yet available for general production use. Activity was supposed to enable pre-rendering offscreen content for instant UI transitions, but it remains behind an experimental flag. The React Compiler is available but not yet part of the default setup for most build tools outside Next.js. Full asset loading integration is also still evolving.

Has the React ecosystem fully adopted React 19?

Major libraries like React Query and React Router support it, but some smaller libraries still need updates for Server Components and the new ref handling. The ref-as-prop change (removing the need for forwardRef) was straightforward for most libraries, but Server Component compatibility requires more significant changes. Component libraries that rely heavily on client-side state and effects need "use client" directives, which works but means they do not benefit from RSC's zero-JavaScript advantage.

Collaboration

Need help with a project?

Let's Build It

I help startups and established companies design, build, and scale world-class digital products. From deep technical architecture to pixel-perfect UI — let's bring your vision to life.

SH

Article Author

Sadam Hussain

Senior Full Stack Developer

Senior Full Stack Developer with over 7 years of experience building React, Next.js, Node.js, TypeScript, and AI-powered web platforms.

Related Articles

Turbopack Is Replacing Webpack: What You Need to Know
Feb 08, 20267 min read
Turbopack
Webpack
Bundler

Turbopack Is Replacing Webpack: What You Need to Know

Understand why Turbopack is replacing Webpack as the default bundler in Next.js, with benchmarks showing 10x faster builds and what it means for you.

pnpm vs Yarn vs npm: Package Managers in 2026
Jan 22, 20266 min read
pnpm
Yarn
npm

pnpm vs Yarn vs npm: Package Managers in 2026

Compare pnpm, Yarn, and npm in 2026 across speed, disk usage, monorepo support, and security to choose the right package manager for your team.

OpenTelemetry Is Becoming the Observability Standard
Jan 05, 20265 min read
OpenTelemetry
Observability
DevOps

OpenTelemetry Is Becoming the Observability Standard

Learn why OpenTelemetry is becoming the standard for distributed tracing, metrics, and logging, and how to instrument your Node.js and Next.js apps.