React 19.2 が出たので内容抑えておく
React19がリリースされたのが去年の12月。。その半年後に19.1がリリース。。そして10月1日に早くも19.2が登場です。
本当にフロントエンド界隈の進化は早いですね!AIの動向も追いながら技術のキャッチアップを行うのは本当に大変です。
なんとなくこの記事が目についた方が簡単に変更内容をキャッチアップできるように押さえておくと良さそうなものをまとめておきます。
TL;DR
Reactの新機能である<Activity />とuseEffectEventなどの紹介
新しいReact DOM機能のPartial Pre-renderingの紹介
その他の変更点の紹介
Reactの新機能の紹介
Activityコンポーネント
<Activity> は、UIを部分的に可視/非可視モードで制御しつつ、状態や DOM の内容を保持できるようにするためのラッパーコンポーネントです。
これまで、UIを「条件付きレンダリング」で消したり再描画したりする際には、再マウントによって内部状態が失われてしまう為、維持したい場合はCSSで隠す方法などが取られていましたがこの方法だと隠れていても結局レンダーコストが生じてしまうという側面がありました。
<Activity> はその課題を解決します。見た目上は非表示にするモードを設定でき、React側ではアンマウント相当の扱いをしつつ、内部のDOM構造と状態は保持しておくという動作をします。
書き方的には以下の感じです
// 従来の記法
{isShowingSidebar && (
<Sidebar />
)}
// Activityによる記法
<Activity mode={isShowingSidebar ? "visible" : "hidden"}>
<Sidebar />
</Activity>
主な特徴と利点
-
状態や DOM の破棄を防ぐ
例えば、入力フォームでユーザーが書きかけている内容を保持しておきたいが、一旦隠したいというケースに適します。再表示時にまた入力中の状態から戻せます。(このメリットが一番大きい) -
副作用(Effect)を停止できる
隠れている間は不要なサブスクリプションやタイマー、ストリーム接続などを停止することができます。これにより、リソース消費を軽減できます。 -
バックグラウンド準備(プリレンダリングなど)の助けに
後から見せる可能性のあるコンテンツを“hidden”で描画しておき必要になったタイミングでvisibleに切り替え早く反映できるようにする、という事が可能になります。 -
パフォーマンス制御
可視部分のインタラクティブ性を損なわずに、非表示部分を低優先度で処理するようなスケジューリングが内部で行われます。 -
副作用の明示的なクリーンアップの促進
hiddenモードに移行するとEffectのクリーンアップが走るため、Effectの戻り関数(cleanup)で外部リソースの解除などをきちんと記述しておく設計を促す、という副次的なメリットもあります。
useEffectEvent
useEffectEventはEffect(useEffect 等)の中だけで呼び出すイベント用コールバックを作るフックです。これを使うと、最新のprops / stateを読みつつも、Effectの依存に含めたくない値を非リアクティブに読むことができます。いわゆる「stale closure 問題」を、安全に回避できます。
// 従来のコード
function ChatRoom({ roomId, theme }) {
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.on('connected', () => {
showNotification('Connected!', theme);
});
connection.connect();
return () => {
connection.disconnect()
};
}, [roomId, theme]);
これだとthemeが変更された場合、当然useEffectの処理が再度実行されますのでもしthemeの変更に依存したくない場合はLintの警告を無視して依存配列を[roomId]のようにしていました。
このような記述は非推奨でありバグの原因となります。
useEffectEventはこの問題を解決してくれます!
// useEffectEventの場合
function ChatRoom({ roomId, theme }: { roomId: string; theme: 'light' | 'dark' }) {
// ❶ Effectから呼ぶ“イベント”のロジックをここに分離
const onConnected = useEffectEvent(() => {
// ここでは常に最新の theme が読める
showNotification('Connected!', theme)
})
// ❷ 接続の確立/解放は roomId だけに反応させる
useEffect(() => {
const conn = createConnection(roomId)
conn.on('connected', () => onConnected()) // ← Effect Event をここから呼ぶ
conn.connect()
return () => conn.disconnect()
}, [roomId])
}
ポイントはuseEffectEvent(onConnected)の中では最新の値を読む一方で、useEffectの依存は必要最小限に保てることです!
その他
cacheSignal
cache()のライフサイクルが終わるタイミングを把握できるようになる機能が追加されました。キャッシュ結果が不要と判断されたタイミングでクリーンアップ処理や中断処理を行えます。
Performance Tracks
Chrome DevTools のパフォーマンスプロファイラ向けに新しいカスタムトラック (custom tracks) を追加し、React アプリのパフォーマンス指標をより詳細に可視化できるようになりました。
新しいReact DOM機能
Partial Pre-rendering
Partial Pre-renderingはページの中ですぐ表示したい静的な部分と個別ユーザーやリクエスト依存の動的領域を“同じルート”内で両立させる戦略です。
静的部分は先にプリレンダしてCDNから即返し、動的部分は後からレンダを再開(resume)して埋め込みます。これにより初期体感を改善しつつ、パーソナライズも維持できます。
いわゆるSSRとSSGの良いとこ取りをした感じです!
例えばECサイトのトップ、ヘッダー、ヒーローのような静的部分は即出し、在庫、価格のような動的なパーソナライズ部分は後から再開することが可能になります。
その他
SSR における Suspense 境界のバッチ処理
SSRでストリーミングを使う場合クライアントでのレンダー時で、Suspense境界の表示タイミングが異なることがあったが改善されたようです。
Node における Web Streams 対応 for SSR
Node.js上でのストリーミングSSRに対してWeb Streamsをサポートするようになります。
ただし、Node環境では従来のNode Streamsを優先使用することが推奨されており、パフォーマンスや圧縮対応の観点からWeb Streamsは補助的に使われるべきだとされています。
eslint-plugin-react-hooks v6
デフォルトでflat configを採用、かつ新しいReactコンパイラ対応ルールをオプトインで有効化できるようにしています。
useId のデフォルト接頭辞の更新
- 19.0.0::r:
- 19.1.0:«r»
- 19.2:r
view-transition-nameやXML1.0の名称との互換性を確保するために変更したそうです。
終わりに
以上React19.2の大まかな変更内容になります!少しでもキャッチアップのサポートになっていれば幸いです。
また、詳しく内容を確認したい方はぜひ公式のドキュメントをご覧ください。
追記
React Confに参加された方がまとめたブログが面白いので興味ある方はこちらも併せてどうぞ!
Discussion