19.0.0 (2024年12月5日)
新機能
React
- Actions:
startTransition は非同期関数を受け入れ可能になりました。これらの関数は「Actions」と呼ばれ、状態をバックグラウンドで更新し、UI を一度にコミットします。Actions は非同期リクエストのような副作用を実行でき、Transition が完了する前に処理の完了を待機します。
useActionState: Transition 内で Actions を順序付けし、状態にアクセスできる新しいフックです。初期状態と reducer を受け取ります。
useOptimistic: Transition の進行中に状態を更新する新しいフックです。Transition が完了すると、状態は新しい値に更新されます。
use: レンダリング時にリソースを読み取れる新しい API です。Promise または Context を受け取り、Promise が渡された場合は値が解決されるまで中断されます。
ref を prop として使用: forwardRef を必要とせずに ref を prop として使用できます。
- Suspense の兄弟要素のプリウォーミング: コンポーネントが中断されると、React は最も近い Suspense 境界のフォールバックを即座にコミットします。
React DOM クライアント
<form> action prop: Form Actions は自動的にフォームを管理し、useFormStatus と統合されます。成功時にはフォームを自動的にリセットします。
- ドキュメントメタデータのサポート: ドキュメントメタデータタグをコンポーネントからネイティブにレンダリングできます。
- スタイルシートのサポート: Suspense 境界のコンテンツを公開する前に、クライアントの
<head> にスタイルシートを挿入します。
- 非同期スクリプトのサポート: コンポーネントツリーのどこからでも非同期スクリプトをレンダリングできます。
React DOM サーバー
prerender および prerenderToNodeStream API を追加: 静的サイト生成向けの API で、Node.js ストリームや Web ストリームなどのストリーミング環境で動作するよう設計されています。
React サーバーコンポーネント
- RSC 機能: ディレクティブ、サーバーコンポーネント、サーバー関数が安定化しました。サーバーコンポーネントを含むライブラリは、React 19 をピア依存関係としてターゲットにできるようになりました。
非推奨予定
element.ref へのアクセス: element.props.ref を推奨し、element.ref へのアクセスは非推奨になります。
react-test-renderer: React 19 では react-test-renderer が非推奨警告を出力し、Web 利用向けに並行レンダリングへ移行します。
主な変更点
React
- 新しい JSX 変換が必須: バンドルサイズを改善し、React を import せずに JSX を使えるようにする新しい JSX 変換が必要です。
- レンダリングエラーは再スローされない: エラーが Error Boundary に捕捉されなかった場合、
window.reportError に報告されます。
propTypes の削除: propTypes の使用は静かに無視されます。TypeScript への移行が推奨されます。
- 関数の
defaultProps を削除: 代わりに ES6 のデフォルト引数を使用できます。
- 文字列 refs の削除: 文字列 refs の使用は ref コールバックへ移行する必要があります。
React DOM
react-dom/test-utils の削除: act は react-dom/test-utils から react に移動しました。その他のユーティリティは削除されます。
ReactDOM.render, ReactDOM.hydrate の削除: 並行レンダリング向けの ReactDOM.createRoot および ReactDOM.hydrateRoot に置き換えられます。
注目すべき変更点
React
<Context> をプロバイダーとして使用: <Context.Provider> の代わりに <Context> をプロバイダーとしてレンダリングできます。
- カスタムエレメントのサポート: React 19 はすべてのカスタムエレメントテストを通過します。
- StrictMode の変更点:
useMemo と useCallback は最初のレンダリングのメモ化結果を再利用します。
React DOM
- ハイドレーションエラーの差分表示: 不一致が発生した場合、React 19 は不一致コンテンツの差分を含む単一のエラーを記録します。
TypeScript の変更点
- 暗黙的な return を禁止: refs はクリーンアップ関数のみを受け入れます。暗黙的な return はエラーを発生させます。
useRef の初期引数が必要: 初期引数は必須です。
- 厳格な
ReactElement タイピング: React 要素の props は今後 any ではなく unknown がデフォルトになります。
1件のコメント
Hacker Newsの意見
ここでなぜこんなに多くの人が React を嫌っているのか、よく分からない
Laravelと素のJSでキャリアを始めたが、Reactを使ってからはスケーラブルなアプリを作ることが現実的に感じられ、フロントエンドも面白くなった
会社が変わってもReactは再び取り組みやすく、TypeScript対応と大きなエコシステムのおかげで、何でもかなり簡単に作って育てられるという感覚がある
新機能がなぜ人々を怖がらせるのかも分からない。今でもSPAや従来のやり方で作れるし、NoSQL DBやSpring Boot、Kotlinが出てきたときも、使いたくなければ使わなければよかったのと似ている
Jetpack ComposeとSwiftUIもReactに触発されたものだと思っていた。以前Androidのドキュメントで見た気がするが、今は見つけられない
ただ、まだ何十年もの経験があるわけではないので、昔の大規模チームがjQueryや素のJSでAirbnbのような大きなWebアプリを作るのがどれほど楽しかったのかは分からない。今では状態管理、DOM操作、副作用を素のJSでどう解決するのか想像するのも難しくなっている
いつかは自分も新しいフレームワークに文句を言いながら、Reactはよかったと言うのかもしれない
たいていの論理は「フロントエンドは常に新しくてキラキラしたものを追いかけていて、Reactもその一つ」というものだが、Reactは2013年から存在し、2015年ごろからはかなり主流だった
また、フレームワークやライブラリが 複雑さ を増すとも言われるが、具体的にどんな複雑さなのかと尋ねると、ほとんど答えが返ってこない。フレームワークなしで意味のあるアプリを作ると、結局は管理もテストも文書化も不十分な独自フレームワークを発明することになる
コンパイルやバンドリングの段階にもよく不満が出るが、今ではExpo、Next.js、Meteorのような実証済みのフレームワークがあるので、webpack設定やビルドパイプラインを自分で組む理由はほとんどない
あらゆる場所にWebフレームワークを押し込む流れは、この10年間で遅く壊れやすいサイトを量産し、過剰に設計されているにもかかわらず、2008年のユーザー体験から大きく改善していないことも多かった
ある種のフロントエンド開発者にとっては、質問が何であれ答えはReact / Node / Vite / Angular / Vue / Nuxt / Next / Bun / Deno / Svelte / SvelteKitなどの組み合わせであり、可能ならKubernetesが支配する数十のDockerスウォーム上で動くべき、ということになる。「履歴書をオンラインに載せたい? じゃあこれから3週間、アプリの状態遷移図を描こう」といった具合だ
Reactが特に叩かれるのは、フレームワークの流行を追う人たちはすでに次のキラキラしたものへ移り、もともとこうしたフレームワークを嫌っていた人たちは嫌い続けているため、今ではこの混乱を擁護する人が残っていないからに見える。ほかのフレームワークも、時間がたてば同じ運命をたどる気がする
実際の動作の多くが隠されていて直感的でなく、ミスしやすく、性能の低いUIも簡単に書けてしまう
何が何回実行されるのか、依存配列に何を入れるべきか、
useCallbackとuseEffectには何を入れるべきかを常に考えなければならず、認知負荷が大きいコミュニティの一部は、プロジェクトに不要なReact依存関係まで推奨して、オーバーヘッドと複雑さだけを増やすこともある
ビジネスロジックとUIロジックも混ざりやすい
しばらくの間、SPAはMPAに比べて欠点があったが、最新のWeb標準とSPAフレームワークへのサーバーサイドレンダリング導入により、その問題は今ではほぼ解決されている
https://www.youtube.com/watch?v=b2F-DItXtZs
素晴らしいリリースだが、今 フロントエンド開発 に入門する人は少し気の毒だとも思う
「Transition の中で Action を順序付けし、action の状態と pending 状態にアクセスする新しい hook で、Action を呼び出せる reducer と初回レンダーに使う初期状態を受け取り、form action prop に渡された場合にフォームの漸進的拡張をサポートするための任意の文字列も受け取る」といった説明は、機能としては良さそうに見えてもあまりに冗長
今日 Web サイト開発を始めるなら、どこから手を付ければいいのか途方に暮れそう
それでも React は依然として優れたフレームワークで、今回のリリースも改善ではある。批判は React だけではなく、フロントエンド開発全般に近い
昔ながらの サーバーサイドレンダリング に HTMX のようなものを使うほうがずっと良い
React フロントエンド開発で4年間稼いできて、2005年に初めて Web サイトを作ったが、今あるクライアント案件を React から HTMX に移行しているところで、ずっと良いと感じている
バグも少なく、hook の誤用で起きる落とし穴も少ない
クライアントサイドレンダリングが必要なら Solid か Vue を使うが、React は避ける。選択肢がないなら幸運を祈る
単方向バインディング、仮想 DOM、再レンダリング、差分計算という基本前提に根本的に納得できなかった。ブラウザメモリを2倍使い、すべてのインタラクションごとに全体を再レンダリングして差分計算するということだから
当時の答えは「まず安定させ、その次に速くしよう」だったが、今では速くするためのハック的な構造だらけで、速くも安定もしていない
正直な双方向バインディングのフレームワークなら、少なくとも速さは保証され、安定性は経験から来るものだと思う。React はただ混乱している。最初のフロントエンド入門が React だったエンジニアたちは、学ぶよりも一度消して学び直すほうがはるかに難しそうで気の毒だ
VBScript、JS、jQuery、Mootools、Applets、ActionScript、YUI/Ext/Sencha、Backbone、Knockout、Angular 1、Angular 2、React、Vue 1 まで経験してきた立場からは、Flutter を試してみてと言いたい。本当に新鮮
ただし Dart が問題。Flutter が TypeScript だったなら理想郷にもう少し近かったはずだが、Dart がフロントエンドの終わりなき churn 精神を生かし続けている
Web 標準も全体として、これまでになく安定している。若い開発者は、ページを複数ブラウザで正しく見せるために何百ものレイアウトの小技を覚える必要がなく、ときには単一ブラウザに合わせるためだけのハックも少なくて済む
JavaScript 疲れは理解できるが、今は学ぶのに最も良い時期の一つだと思う
全体が本当に まともな開発 のように感じられ、以前の状況と比べると新鮮な空気のようだった
開発者の99%なら、アプリがある程度成長するまでそうした機能は必要ないし、最後まで必要ないかもしれない。React が強制しているわけでもない
React のようなクライアントサイドフレームワークを一時は好きだったが、結局、可能なあらゆる場所に 複雑さ を足していたのだと気づいた
バックエンド、フロントエンド、DevOps スタック、どこにでも複雑さが入り、その分散した複雑さを同期するために、さらに多くの層が追加され続けるのだろう
データやモデルが変わったときに UI が自動で再レンダリングされるのは正しい方向
細部のやり方は議論できるが、データが変わるたびに命令型で UI を直接変更する方法は、コードベースやチーム規模の面で長く持ちこたえにくい
Web ブラウザが本来意図していない方法でボックスをレンダリングさせようとして、膨大な複雑さを上乗せし、コーディングパラダイムを変えるという名目で生産性とツール体系も大きく失った
優れたアイデアと実装はあったが、それだけの価値があったのかは分からない。一種の雇用安定装置だったのかもしれないとも思う
ReactJS だけの問題ではなく、JavaScript エコシステム全体がライブラリとツールで狂騒状態になっていたが、React は特に始めるのが面倒で、結局まともな時間内に hello world アプリを作れるように create react app が出てきた
クラスコンポーネント API を hook に変えた理由を理解しようと期待するのはやめた
もっとシンプルなフレームワークを選ぶこともできるし、サーバーオーケストレーションを避けることもできる
選択肢がないなら、シンプルなスタックで効率面の優位を持てると信じるプロジェクトを自分で始めてみることもできる
今回のリリースで最も良い部分の一つは、ref を prop として使えるようになったこと。これでもう
forwardRefは不要になるブログ記事のほうが読みやすい: https://react.dev/blog/2024/12/05/react-19
const error = await updateName(newName);で、なぜupdateNameがエラーを返すのか分からないJS/TS らしく、単に
Errorを投げればいいのでは?これまでのコメント45件のうち「redux」への言及が7回あるなら、ここでは Recoil 系を代表して Jotai に触れておきたい。おそらく React 19 でも特別な変更なしに、すでに動く可能性が高い
フロントエンドの複雑さが十分に大きくなると、ほかの状態管理ツールが必要以上に邪魔になることがある
React が嫌いになったと思っていても、実は終わりのない action 定数の壁、prop の配管、ネストした provider/context との戦い、pub-sub への逃避に疲れているだけなら、Jotai のようなものを一度試してみる価値はある
https://github.com/pmndrs/zustand
https://github.com/pmndrs/valtio
Jotai は手作業のボイラープレートが多すぎるように感じられ、Valtio はプロキシの「魔法」が多いので、個人的には好きでもチームにとって良い選択かは確信が持てない
Zustand はボイラープレートと魔法の中間にあるので、現在進行中の大きなプロジェクトで採用した
数年前に React アプリの作業を始めたとき、目にした状態管理パッケージはどれもそうした用語だらけで、今も変わらない
結局、そういうものから離れて仕事に集中するために自分で解決策を作り [1]、本番環境でうまく動いている。同じように動く一般的な選択肢がないのは残念だ
[1] https://github.com/facepunch/react-class-model
context hook の良いところは合成可能なことで、キャッシュされたクエリと組み合わせれば、かなり保守しやすいパターンを作れる
Jotai がここでどのような 実質的な改善 を提供するのか知りたい
redux や sagas を二度と扱わずに済むことを心から願っている
新しく導入された機能の多くは気に入らない
Actions と
useActionState/useOptimisticフックは大きな 複雑さの罠 のように見える。useフックは名前があまりに情報量不足で、コンポーネント内部で作られた promise を処理しないきっと良い理由があるのだろうが、promise を prop として渡し、
useフックで処理するやり方は、現在の回避策よりも多くの複雑さを生みそうだServer Components もかなり複雑そうで、まだ扱う機会がないのは幸いだ
hydration エラーメッセージの改善は歓迎できるし、provider として使える変更や ref を prop として使える変更は良い品質改善だ
全体として、SPA を作る用途なら React/Preact は好きだ。MUI のような機能豊富なコンポーネントライブラリと、Preact Signals のようなシンプルな状態管理ソリューションを組み合わせれば、SPA 制作はかなり直感的になる
ただ、複雑さが少しずつ入り込んでくることを懸念している。リリースノートの新しいフックの説明を読むだけでも、認知負荷が大きく感じられる
一方で React Compiler はぜひ必要なツールだ。プログラマーが典型的な最適化をコンポーネント内部に直接書かなくて済むようになり、コンポーネントはより複雑でなくなるはずだ
リリースと Vite などとの統合を楽しみにしているし、聞いたところでは Preact もサポートする予定らしい
useAPI は、フック共通の接頭辞とは別の名前に変えたほうがいいと思うReact フックに新しく入門した人が、
useは条件付きで呼び出せるが通常の hooks はそうできないと知ったら、混乱しそうだ並列 Suspense の問題を解決するためにリリースを遅らせたのは本当に喜ばしい
まだ使ってはいないが大いに期待しており、全体として素晴らしいリリースだ
速報: custom elements を完全にサポート。つまり Web Components だ