React Compiler (React 19)で不要になるメモ化コードと移行手順

React Frontend Performance JavaScript
結論

React Compilerにより useMemo / useCallback の手動記述は不要になり、自動最適化されます。

// React 19公式仕様:React Compiler 導入後のコンポーネント(手動メモ化フック一切不要)
export function ComponentList({ items, filterText }) {
  // ⭕ useCallback や useMemo を一切書かなくても、ビルド時に自動でメモ化される
  const filteredItems = items.filter(item => item.name.includes(filterText));

  const handleClick = (id) => {
    console.log('Clicked', id);
  };

  return (
    <ul>
      {filteredItems.map(item => (
        <ItemKey key={item.id} item={item} onClick={handleClick} />
      ))}
    </ul>
  );
}

React公式仕様:React Compiler の自動最適化

React 19 のエコシステムとして提供される React Compiler は、ビルド時(Babel / Vite プラグイン)に抽象構文木(AST)を解析し、コンポーネント内のデータフローと依存関係を追跡して、自動的にメモ化処理を注入するコンパイラです。

この導入により、開発者が手動で useMemo, useCallback, React.memo を記述する作業が原則不要となりました。


実際に起こる事故:Rules of React 違反による「サイレント・スキップ」現象

React Compiler公式ドキュメント(react.dev/learn/react-compiler)で明記されている通り、コンパイラはコードの安全性を最優先するため、「Rules of React(Reactの規約)」に違反しているコンポーネントを見つけると、エラーを出さずにそのコンポーネントの自動メモ化処理のみを静かにスキップ(無効化)します。

メモ化が静かにスキップされるコード例

// ❌ 違反例:描画中に既存オブジェクト/props を直接ミューテーション(変更)している
function IncorrectComponent({ user }) {
  // レンダー時に props のオブジェクトを変更(純粋関数違反)
  user.lastViewed = Date.now(); 
  
  // ⭕ コンパイラはこのコンポーネントの自動メモ化を断念してスキップする
  return <div>{user.name}</div>;
}

導入と移行手順

  1. プロジェクトのビルド設定(vite.config.tsnext.config.js)に React Compiler プラグインを追加する
  2. eslint-plugin-react-compiler を導入し、エディタ上で Rules of React 違反箇所(ミューテーションや副作用の誤用)を可視化・修復する
  3. 既存の useMemo / useCallback はそのまま動作するため、段階的にリファクタリングして手動フックを削除していく