Skip to main content
Ganesh Joshi
Back to Blogs

React 19 and the React Compiler: what's new and how to try it

February 14, 20265 min read
Tutorials
Code editor or development workspace, React

React 19 shipped in late 2024 with significant improvements to async handling, data fetching, and developer experience. The React Compiler, reaching stable in 2025, automates performance optimizations that developers previously handled manually. Together, they simplify React development while improving performance.

React 19 overview

React 19 focuses on making async operations and data handling simpler. The major additions include Actions, the use() hook, and various DX improvements.

Feature Description
Actions Async functions for transitions with built-in pending state
use() hook Read promises and context conditionally
ref as prop No more forwardRef for passing refs
Improved hydration Better error recovery and partial hydration
Document metadata Native support for title, meta, link tags

Actions and useTransition

Actions are async functions wrapped in transitions. React tracks pending state automatically:

'use client';

import { useTransition } from 'react';

export function UpdateButton({ userId }: { userId: string }) {
  const [isPending, startTransition] = useTransition();

  async function handleUpdate() {
    startTransition(async () => {
      await updateUser(userId);
      // React handles pending state
    });
  }

  return (
    <button onClick={handleUpdate} disabled={isPending}>
      {isPending ? 'Updating...' : 'Update'}
    </button>
  );
}

No manual useState for loading. React manages the pending state through the transition.

The use() hook

use() reads a promise or context inside render:

import { use, Suspense } from 'react';

async function fetchUser(id: string) {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}

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

export default function Page({ params }: { params: { id: string } }) {
  const userPromise = fetchUser(params.id);

  return (
    <Suspense fallback={<div>Loading...</div>}>
      <UserProfile userPromise={userPromise} />
    </Suspense>
  );
}

Key differences from other hooks:

  • Can be called conditionally
  • Works with promises and context
  • Must be inside Suspense for promises

ref as a regular prop

No more forwardRef wrapper:

// React 18 - required forwardRef
const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
  return <input ref={ref} {...props} />;
});

// React 19 - ref is a regular prop
function Input({ ref, ...props }: InputProps & { ref?: Ref<HTMLInputElement> }) {
  return <input ref={ref} {...props} />;
}

Simplifies component APIs and reduces boilerplate.

Document metadata

React 19 handles document metadata natively:

function BlogPost({ post }: { post: Post }) {
  return (
    <>
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <link rel="canonical" href={`/blog/${post.slug}`} />
      <article>{post.content}</article>
    </>
  );
}

React hoists these elements to <head> automatically. This works alongside Next.js metadata or as a simpler alternative.

The React Compiler

The React Compiler analyzes your code at build time and adds memoization automatically.

How it works

Without the compiler, you manually optimize:

// Manual memoization (pre-compiler)
const MemoizedChild = React.memo(Child);

function Parent({ items }) {
  const sortedItems = useMemo(() => items.sort(), [items]);
  const handleClick = useCallback(() => console.log(items), [items]);

  return <MemoizedChild items={sortedItems} onClick={handleClick} />;
}

With the compiler:

// Compiler handles memoization
function Parent({ items }) {
  const sortedItems = items.sort();
  const handleClick = () => console.log(items);

  return <Child items={sortedItems} onClick={handleClick} />;
}

The compiler analyzes dependencies and adds memoization where beneficial.

What the compiler optimizes

Optimization Manual approach With compiler
Computed values useMemo Automatic
Callback references useCallback Automatic
Component re-renders React.memo Automatic
Expensive calculations useMemo Automatic

Installing the compiler

For Babel-based builds:

npm install babel-plugin-react-compiler
// babel.config.js
module.exports = {
  plugins: [
    ['babel-plugin-react-compiler', {
      // Options
    }],
  ],
};

For Next.js 15+:

// next.config.js
module.exports = {
  experimental: {
    reactCompiler: true,
  },
};

ESLint plugin

Add the ESLint plugin to catch patterns the compiler can't optimize:

npm install eslint-plugin-react-compiler
// eslint.config.js
import reactCompiler from 'eslint-plugin-react-compiler';

export default [
  {
    plugins: {
      'react-compiler': reactCompiler,
    },
    rules: {
      'react-compiler/react-compiler': 'error',
    },
  },
];

Compiler limitations

The compiler can't optimize everything:

Pattern Issue
Non-idempotent functions Side effects in render
Mutable data Modifying objects/arrays in place
Dynamic hooks Hooks called conditionally (except use())
External mutations Mutating data outside React's control

The ESLint plugin warns about these patterns.

Migration guide

Step 1: Upgrade to React 19

npm install react@19 react-dom@19

Update type definitions:

npm install -D @types/react@19 @types/react-dom@19

Step 2: Fix breaking changes

Most code works unchanged. Watch for:

  • Remove deprecated propTypes and defaultProps on function components
  • Update forwardRef usage (optional but recommended)
  • Check custom hooks that rely on render timing

Step 3: Enable the compiler

Start with the ESLint plugin to identify issues before enabling the compiler:

// Enable ESLint plugin first
rules: {
  'react-compiler/react-compiler': 'warn',
}

Fix warnings, then enable the compiler in your build.

Step 4: Remove manual memoization

Gradually remove useMemo, useCallback, and React.memo. The compiler handles them. Keep manual memoization only where the compiler warns or for specific edge cases.

Using with React 18

The compiler works with React 17 and 18:

npm install react-compiler-runtime
// babel.config.js
module.exports = {
  plugins: [
    ['babel-plugin-react-compiler', {
      runtimeModule: 'react-compiler-runtime',
    }],
  ],
};

Performance impact

In benchmarks, the compiler provides:

Metric Improvement
Re-render reduction 20-40% fewer renders
Bundle size Similar (compiler adds small runtime)
Build time Slightly longer (compiler analysis)
Runtime performance Matches or exceeds manual optimization

The compiler is conservative—it only memoizes when provably safe.

Summary

React 19 simplifies async handling with Actions, adds use() for reading promises, and removes forwardRef boilerplate. The React Compiler automates memoization at build time, letting you write simpler code without sacrificing performance. Upgrade to React 19 for new features, add the compiler for automatic optimization, and gradually remove manual useMemo/useCallback calls.

Frequently Asked Questions

React 19 introduces Actions for async state management, the use() hook for reading promises and context, ref as a regular prop (no forwardRef needed), improved hydration, and better error handling with error boundaries.

The React Compiler is a build-time tool that automatically memoizes components and values. It replaces manual useMemo, useCallback, and React.memo in many cases, making code simpler while maintaining performance.

The compiler handles most memoization automatically. You can remove useMemo and useCallback in many cases. Keep them only for specific edge cases the compiler warns about or when you need explicit control.

Install babel-plugin-react-compiler and add it to your Babel config. For Next.js 15+, set experimental.reactCompiler to true in next.config.js. Add the ESLint plugin to catch patterns the compiler can't optimize.

Yes, the compiler supports React 17 and 18 via the react-compiler-runtime package. You don't need to upgrade to React 19 to use the compiler, though React 19 provides additional features.

Related Posts