AgentSkillsCN

react-19-compiler

React 19 的模式与 React Compiler 优化指南。了解何时应采用手动记忆化,而非完全依赖编译器优化;同时善用 useActionState 和 useFormStatus 等新钩子。

SKILL.md
--- frontmatter
name: react-19-compiler
version: 1.0.0
lastUpdated: 2026-01-18
description: React 19 patterns and React Compiler optimization guidance. Understand when to use manual memoization vs letting the compiler optimize, and leverage new hooks like useActionState and useFormStatus.
tags: [react, react-19, react-compiler, memoization, useActionState, useFormStatus, server-components]
author: Szum Tech Team
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__get-library-docs
context: fork
agent: general-purpose
user-invocable: true
examples:
  - When should I use useMemo with React Compiler enabled
  - How to use useActionState for form handling
  - Implement form with useFormStatus for pending state
  - Should I use React.memo with the compiler

React 19 & React Compiler Skill

React 19 patterns and React Compiler optimization guidance for Next.js applications.

Reference Files:

Project Configuration

This project has React Compiler enabled:

typescript
// next.config.ts
const nextConfig: NextConfig = {
  experimental: {
    reactCompiler: true
  }
};

With React Compiler enabled, you can safely remove most manual memoization (useMemo, useCallback, React.memo).

Quick Start

Let the Compiler Optimize

typescript
// ✅ Good - Let compiler handle optimization
function Component({ items, sortBy }) {
  const sorted = [...items].sort((a, b) => a[sortBy] - b[sortBy]);
  return <List items={sorted} />;
}

// ❌ Unnecessary with compiler
function Component({ items, sortBy }) {
  const sorted = useMemo(() => {
    return [...items].sort((a, b) => a[sortBy] - b[sortBy]);
  }, [items, sortBy]);
  return <List items={sorted} />;
}

Form Handling with useActionState

typescript
"use client";

import { useActionState } from "react";
import { submitForm } from "./actions";

function ContactForm() {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const result = await submitForm(formData);
      if (!result.success) {
        return result.error;
      }
      return null;
    },
    null
  );

  return (
    <form action={submitAction}>
      <input type="text" name="message" />
      <SubmitButton />
      {error && <p className="text-red-500">{error}</p>}
    </form>
  );
}

// ✅ useFormStatus must be in child component
function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? "Sending..." : "Send"}
    </button>
  );
}

Key Concepts

React Compiler Benefits

The React Compiler:

  • Automatically memoizes components and values at build time
  • Eliminates need for manual useMemo, useCallback, React.memo
  • Identifies bottlenecks and applies optimizations intelligently
  • Reduces boilerplate and potential dependency-related bugs

When Manual Memoization IS Still Needed

See when-to-memoize.md for details. Key scenarios:

  1. External library callbacks - Non-React code expecting stable references
  2. Complex context values - When context updates trigger cascading re-renders
  3. Performance-critical loops - Thousands of items with expensive computations

New React 19 Hooks

HookPurposeKey Caveat
useActionStateForm state managementAccepts async action, returns [state, action, isPending]
useFormStatusForm submission statusMust be called from child component inside <form>
useOptimisticOptimistic UI updatesFor instant feedback before server confirmation

File Locations

PurposeLocation
Client componentsfeatures/*/components/*.tsx with "use client"
Server componentsapp/**/*.tsx, features/*/components/*.tsx (default)
Server actionsfeatures/*/server/actions/*.ts

React Compiler Configuration

The compiler is enabled in next.config.ts:

typescript
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  experimental: {
    reactCompiler: true
  }
};

export default nextConfig;

Migration Checklist

When working on this codebase:

  1. Remove unnecessary memoization - Let compiler handle it
  2. Keep memoization for external libs - Document why it's needed
  3. Use useActionState for forms - Replaces manual state + useTransition
  4. useFormStatus in child components - Not in same component as form
  5. Default to Server Components - Only add "use client" when needed

Running and Testing

bash
# Type check
npm run type-check

# Dev server (compiler active)
npm run dev

# Production build (full optimization)
npm run build

Related Skills

  • server-actions - For implementing server actions with React 19 patterns
  • storybook-testing - For testing components with play functions