SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

フロントエンド開発における定番ライブラリ「React」の最新バージョン解説

React 19.2新機能ガイド──Activity/useEffectEventを軸に見るパフォーマンス改善の新機能

フロントエンド開発における定番ライブラリ「React」の最新バージョン解説 第6回


useEffectEvent:Effect内イベントハンドラーと依存関係の分離

 useEffectEventは、React 19.2で新たに導入されたフックで、Effect(副作用)内で発生する「イベント的な処理(=Effect Event)」を、従来のuseEffectの依存配列ロジックから切り離して扱えるようにするものです。

useEffectの問題

 以下のように、時計を表示するコンポーネントを考えます。ここでmakeClockは指定されたタイムゾーンの現在日時を返す関数だとします。

[リスト4]useEffect の課題となるコード例 ※ファイル名: samples/02/src/index.jsx
function makeClock(timeZone) {
  return new Date().toLocaleString("ja-JP", { timeZone });
}

useEffect(() => {
  console.log(`mounted: useEffectEvent なし`);
  const interval = setInterval(() => { // (1) タイマーイベント
    // (1) イベントハンドラー内で時計を更新
    setClock(makeClock(timeZone));
  }, 1000);
  return () => {
    // (1) タイマーをクリーンアップ
    console.log(`cleanup: useEffectEvent なし`);
    clearInterval(interval);
  };
}, [timeZone]); // (2) timeZone が変わるたびに effect を再実行
// ↑ (3) timeZone を依存配列に含めないと、makeClockの引数のtimeZoneが更新されない

 このコードを実行したときの挙動を図6に示します。

図6:サンプルコード02 (useEffectEventなし) の実行例
図6:サンプルコード02 (useEffectEventなし) の実行例

 Consoleのログを見ると、timeZoneプロパティが変わるたびにEffectが再実行されていることがわかります(1)。

 このtimeZoneの変更により、タイマーイベントが不必要に中断され、更新周期が乱れることになります。また、仮にtimeZoneが頻繁に変わる場合などは、パフォーマンス低下が発生する可能性もあります。

 ここで注目すべきは、useEffectの依存関係に書かれた変数(timeZone、(2))が、実際にはEffect内では参照されず、タイマーイベント内でのみ参照される点です。

 ではuseEffectの依存関係からtimeZoneを外せばいいのでしょうか(3)。この場合、たしかにタイマーの再設定は発生しなくなりますが、今度はtimeZoneが変わってもタイマーイベント内で参照される値が更新されないため、常に最初に渡されたタイムゾーンのままになってしまい、正しい動作が得られなくなります。

useEffectEventの活用

 ここで登場するのがuseEffectEventです。これを使うと、先の問題をうまく解決できます。以下のように書き換えてみましょう。

[リスト5]useEffectEvent を使ったコード例 ※ファイル名: samples/02/src/index.jsx
// (1) useEffectEvent を使ってイベントハンドラーを定義
const updateClock = useEffectEvent(() => {
  setClock(makeClock(timeZone)); // 常に最新の timeZone を参照できる
});

useEffect(() => {
  console.log(`mounted: useEffectEvent あり`);
  const interval = setInterval(() => {
  // (2) useEffectEvent で定義した関数を呼び出す
    updateClock();
  }, 1000);
  return () => {
    console.log(`cleanup: useEffectEvent あり`);
    clearInterval(interval);
  };
}, []); // (3) timeZone を依存配列に含めない

 useEffectEventを使ってupdateClock関数を定義します(1)。この関数は常に最新のtimeZoneを参照できるため、timeZoneが変わっても正しい値で時計を更新することができます。

 タイマーのイベントハンドラーからはこのupdateClock関数を呼び出します(2)。ここで、useEffectの依存配列にはtimeZoneupdateClockを含めないことが重要です(3)。useEffectEventを使って定義された関数はuseEffectの依存関係に含める必要がありません。

 useEffectEvent使ったこのコンポーネントを実際に動かしてみたのが図7です。

図7:サンプルコード02 (useEffectEventあり) の実行例
図7:サンプルコード02 (useEffectEventあり) の実行例

 UIの挙動は変わっていませんが、Consoleのログを見ると、最初の1回だけEffectが実行されていることがわかります。timeZoneが変わってもEffectの再実行は発生せず、タイマーイベントも中断されないため、安定した更新が行われています。

useEffectEventのユースケースと注意点

 以上の特徴から、useEffectEventは上記のタイマーイベントのほか、ネットワーク通信のコールバック関数やaddEventListenerで登録するイベントハンドラーなど、Effect内で発生するイベントから呼び出される場合に有効です。逆にユーザーイベント(クリックイベントなど)には使用しません。

 また、useEffectEventで定義した関数は、エフェクト内部からのみ呼び出せます。先に述べたように、useEffectEventで定義した関数はuseEffectの依存配列に含めないようする必要があります。これを誤ると、再び不必要なEffectの再実行が発生してしまいます。

 これを防ぐために、React 19.2ではeslint-plugin-react-hooksがバージョン6に更新され、useEffectEventの使用に関するLintルールが追加されています。これにより、誤った依存関係の指定を防止できるため、ぜひ導入を検討してください。

Performance Tracks: Chrome DevToolsでのReactパフォーマンス分析の強化

 React 19.2では、Chrome DevToolsのPerformanceタブに「Scheduler」と「Component」トラックが追加され、Reactのレンダリングパフォーマンスを詳細に分析できるようになりました。

 パフォーマンスは開発者ツールを開き、Performanceタブを選択して、Record(記録)ボタンで測定します。実際に今回のサンプルコード02を実行したときのパフォーマンスプロファイルを図8に示します。

図8:Chrome DevTools の Performance タブでの React パフォーマンス分析
図8:Chrome DevTools の Performance タブでの React パフォーマンス分析

 SchedulerトラックはReactのスケジューリングイベントを示しており、RenderやEffectがどのタイミングで走っているかがわかります。また、Componentトラックは各コンポーネントのレンダリング時間を示しており、Appをはじめ、各コンポーネント(MyClock1MyClock2)のレンダリング時間がそれぞれ表示されているのがわかります。

 これにより、各コンポーネントのレンダリング時間や更新頻度、優先度などを視覚的に把握できるようになり、パフォーマンスボトルネックの特定や最適化が容易になります。

まとめ

 React 19.2では、<Activity>useEffectEventなど、UIの表示制御や副作用ロジックの整理に役立つ新しい選択肢が提供されました。特に<Activity>は、個人的にもこれまで条件付きレンダリングで苦労してきた部分を大幅に改善できると感じています。使い方もシンプルなので、既存プロジェクトへの導入も比較的容易でしょう。

 useEffectEventも、Effect内のイベント処理を整理するのに役立ちます。Lintルールも整備されているため、誤用を防ぎつつ導入できる点も安心です。Performance Tracksも、パフォーマンス分析の強力なツールとして活用でき、開発者にとってとても有益です。

 これまでに紹介した機能に加えて、React 19.2では以下のような新機能や改善点も導入されています。

  • cacheSignal:Reactのcache APIにキャッシュが不要になったときのシグナルを返す関数が追加され、無駄な処理を抑制できるようになりました。
  • Partial Pre-rendering(部分的な事前レンダリング):アプリの静的部分を事前にレンダリングして CDN から提供し、その後残りのレンダリングを再開して動的コンテンツを埋め込むことができます。
  • Suspenseバッチング:従来、SSR(ストリーミングレンダリング)で複数の Suspense 境界が連続していた場合、それぞれが別々にレンダリング順序どおりに出されることがありましたが、これらをバッチ(一括)で表示する遅延制御が導入されました。
  • useIdの接頭辞変更useIdフックで生成されるIDの接頭辞が変更されました。
  • Web Streams対応:Node.jsでSSRをストリーミングするためのWeb Streamsのサポートが追加されました。

 これらについては、次回の記事で詳しく解説する予定です。React 19.2の新機能を活用して、より良い開発者体験とユーザー体験を実現していきましょう。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
フロントエンド開発における定番ライブラリ「React」の最新バージョン解説連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山田 研二(ヤマダ ケンジ)

株式会社MSEN CTO。高校卒業後、大阪大学の研究所で働きながらプログラミングやWebデザインをはじめ、以後20年以上、Webサイト制作や業務システムの構築を手がけています。フリーソフトもいくつか公開しています。好きな言語はC#とTypeScript、趣味は旅行です。 GitHub アカウント WINGSプロジェクト について>有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での 登録メンバ は約50名で、現在も執筆メンバを 募集中 。興味のある方は、どしどし応募頂きたい。 著書 記事 多数。 RSS X: @WingsPro_info (公式)、 @WingsPro_info/wings (メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/22484 2025/11/14 18:28

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー