React 19.2 新機能実践レビュー:Confitで使ってみた3つの機能
目次
こんにちは、ヨンウです。
フロントエンドに興味のある皆様、今年のReact Conf 2025はご覧になりましたか?今回のカンファレンスでは、React 19.2で新たに追加された実用的な機能が大きな注目を集めました。

アトラスでも、学術大会向け自社サービス「Confit」をはじめとする多数のプロダクトをReactベースで開発・運用しています。
今回は、React 19.2の3つの新機能をアトラスのプロダクトのローカル環境で検証してみて、コードの改善前後と使ってみた感想を軽くまとめてみました。
※react@19.2へのアップグレードが必要となります。(Next.js使用時はnext@14.2+ 推奨)
useEffectEvent – useEffect の依存地獄からの脱出
従来のuseEffectは、依存配列に含まれる値が変更されるたびにコールバック全体が再実行されます。
そのため、「状態は常に最新に保ちたいけど、再実行はさせたくない」という状況が頻繁に発生していました。

上記の画像は、公開ウェブサイト内で発表者がコメントをリアルタイムでやり取りできるWebSocket通信を利用した便利な機能の例です。
こちらの機能のコードの一部を例に挙げてみました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** 初期表示時 WebSocket接続処理 */ useEffect(() => { ... // 接続イベント socketRef.current.onopen = () => { sendSocketOpenLog(i18n.language); // 接続情報送信 const param: WebSocketCommentRequest = { action: ACTION_SEND_ROOM, presentationNumber: presentation.presentationNumber }; ... }; ... }, [ sendSocketOpenLog, presentation.presentationNumber, i18n.language // 言語も依存 → 不要な再接続 ]); |
問題点:
i18n.languageが変わるたびにWebSocketが再接続されるため、非効率- しかしログは常に最新の言語で出力する必要があるため、この処理を無くすことはできない
useEffectEventで改善してみると
|
1 2 3 4 5 6 7 |
const sendSocketOpenLog: VoidFunction = useEffectEvent(async () => { if (i18n.language === "en") { // 言語は常に最新状態 await execLogger(getLoggerRequestInfo("Comment sendSocketOpenLog OPEN SOCKET")); return; } await execLogger(getLoggerRequestInfo("ソケット接続開始")); }); |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** 初期表示時 WebSocket接続処理 */ useEffect(() => { ... // 接続イベント socketRef.current.onopen = () => { sendSocketOpenLog(); // 接続情報送信 ... }; ... }, [ sendSocketOpenLog, presentation.presentationNumber ]); // 言語の依存性除去 |
結果:
- 言語変更 → 再接続なし
- ログは常に最新の言語で出力
useEffectのビジネスロジックがすっきり
これにより、
言語は常に最新状態を保ちながら、不要な再接続を起こさないクリーンなuseEffectが書けるようになります。
Activity – 状態を保持する新しいパターン
従来の条件付きレンダリングでは、条件が外れるとコンポーネントがアンマウント → 内部状態が消滅するという致命的な欠点がありました。
|
1 2 3 |
{isEditOpen && ( )} {/* 閉じると入力内容が消える */} |
これをActivity機能を使うことで、CommentInputコンポーネント内の状態を保持できるようになります。
|
1 |
CommentInputコンポーネントの簡単なテストページを作成して、Activityあり・なしで比較してみました。

テスト結果:
- 左(条件付きレンダリング)→ 入力内容が消える
- 右( 使用)→ 入力内容が保持される
React Compiler – 最適化からの解放
これまではレンダリングの最適化をするために、以下のようにコードを使用していました。
|
1 2 3 |
const expensiveValue = useMemo(() => compute(), [deps]); const onClick = useCallback(() => { ... }, [deps]); export default React.memo(Component); |
こうした手動最適化は開発・保守コストを増やし、コードをどんどん複雑にしていました。React Compilerはこの問題を根本的に解決してくれます。
導入するには、npmやyarnでインストールする必要があります。React公式サイトに手順が入っているので、ぜひご参考ください。
|
1 |
npm install -D babel-plugin-react-compiler@latest |
その後、使用しているビルドツールやフレームワークの設定ファイルに追加します。当プロダクトではNext.jsを使っているので、next.configにNext.js公式サイトを参考に、以下のように設定しました。
|
1 2 3 4 5 6 7 |
import type { NextConfig } from 'next' const nextConfig: NextConfig = { reactCompiler: true, } export default nextConfig |
いきなり全体に適用すると問題が起きる可能性があるため、annotationモードで部分的に導入することもできます。
|
1 2 3 4 5 6 7 8 9 |
import type { NextConfig } from 'next' const nextConfig: NextConfig = { reactCompiler: { compilationMode: 'annotation', }, } export default nextConfig |
|
1 2 3 4 |
export default function Page() { 'use memo' // ... } |
また、React Conf 2025でReactチームはuseMemoやuseCallbackで手動メモ化されたコードがあっても、問題なく最適化され、新しいコードではCompilerに任せることを推奨していました。
最後に
今回はReact 19.2の新機能について簡単にご紹介しました。
これまで不便だった部分がきれいに改善され、実用的な機能が多く追加されていましたので、興味がある方は、ぜひ使ってみてください。
アトラスでは今後も新しいフロントエンドの機能を軸に、参加者にとって快適な体験を届けられるようアップデートを進めています。
ありがとうございました。








