DEV Community

Alex Spinov
Alex Spinov

Posted on

React Compiler Has Free Auto-Optimization — Here's Why You Can Delete useMemo and useCallback

React Compiler automatically memoizes your components. No more manual useMemo, useCallback, or React.memo.

What is React Compiler?

React Compiler (formerly React Forget) is a build-time tool that automatically adds memoization to your React components. It understands your code and inserts optimizations that you used to write by hand.

What It Replaces

// BEFORE: Manual memoization everywhere
function TodoList({ todos, filter }) {
  const filteredTodos = useMemo(
    () => todos.filter(t => t.status === filter),
    [todos, filter]
  );

  const handleToggle = useCallback(
    (id: string) => {
      dispatch({ type: 'TOGGLE', id });
    },
    [dispatch]
  );

  return (
    <ul>
      {filteredTodos.map(todo => (
        <MemoizedTodoItem
          key={todo.id}
          todo={todo}
          onToggle={handleToggle}
        />
      ))}
    </ul>
  );
}

const MemoizedTodoItem = React.memo(TodoItem);

// AFTER: Just write normal React
function TodoList({ todos, filter }) {
  const filteredTodos = todos.filter(t => t.status === filter);

  const handleToggle = (id: string) => {
    dispatch({ type: 'TOGGLE', id });
  };

  return (
    <ul>
      {filteredTodos.map(todo => (
        <TodoItem
          key={todo.id}
          todo={todo}
          onToggle={handleToggle}
        />
      ))}
    </ul>
  );
}
// React Compiler adds memoization automatically!
Enter fullscreen mode Exit fullscreen mode

Setup

bun add -d babel-plugin-react-compiler
Enter fullscreen mode Exit fullscreen mode

Vite

// vite.config.ts
export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: ['babel-plugin-react-compiler'],
      },
    }),
  ],
});
Enter fullscreen mode Exit fullscreen mode

Next.js

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

What It Does

The compiler analyzes your component and:

  1. Identifies values that depend on specific inputs
  2. Automatically memoizes them (like useMemo)
  3. Memoizes callback functions (like useCallback)
  4. Skips re-rendering child components when props haven't changed (like React.memo)

Rules of React (Still Apply!)

The compiler relies on you following the Rules of React:

// GOOD: Pure render, no side effects
function UserCard({ user }) {
  return <div>{user.name}</div>;
}

// BAD: Mutating during render
function BadComponent({ items }) {
  items.push('new'); // Mutating props!
  return <div>{items.length}</div>;
}

// BAD: Reading refs during render
function AlsoBad() {
  const ref = useRef(0);
  return <div>{ref.current}</div>; // Don't read refs during render
}
Enter fullscreen mode Exit fullscreen mode

ESLint Plugin

bun add -d eslint-plugin-react-compiler
Enter fullscreen mode Exit fullscreen mode
{
  "plugins": ["react-compiler"],
  "rules": {
    "react-compiler/react-compiler": "error"
  }
}
Enter fullscreen mode Exit fullscreen mode

This catches code that the compiler cannot optimize.

Gradual Adoption

// Opt specific components in
// @compilable
function OptedInComponent() {
  return <div>This will be compiled</div>;
}

// Or opt out
// 'use no memo'
function LegacyComponent() {
  return <div>Compiler skips this</div>;
}
Enter fullscreen mode Exit fullscreen mode

Impact

Before compiler (manual memoization):
- Developer writes useMemo: 3-5 per component
- Bugs from wrong deps: frequent
- Code readability: poor

After compiler:
- Zero manual memoization
- Zero dependency bugs
- Clean, simple code
- Same or better performance
Enter fullscreen mode Exit fullscreen mode

Building optimized React dashboards? Check out my Apify actors — fast data for fast UIs. For custom solutions, email spinov001@gmail.com.

Top comments (0)