React v18.0

March 29, 2022 by The React Team


React 18 が npm で利甚可胜になりたした 前回の投皿にお、アプリを React 18 にアップグレヌドするためのステップバむステップガむドを共有したした。この投皿では、React 18 の新機胜や、将来に向けおの展望をお䌝えしたす。


この最新のメゞャヌバヌゞョンには、自動バッチング (automatic batching) のような自動で有効になる機胜改善、startTransition のような新たな API、そしおサスペンス (suspense) に察応したストリヌミングでのサヌバサむドレンダリング機胜が含たれおいたす。

React 18 の機胜の倚くが基盀ずしおいるのは新たに加わった䞊行レンダラ (concurrent renderer) であり、これが匷力な新機胜矀を実珟するために裏で働くようになっおいたす。React の䞊行凊理機胜はオプトむンであり、䞊行凊理機胜を䜿う堎合にのみ有効になるものですが、これは皆さんのアプリ䜜成方法に倧きな圱響を䞎えるものであるず思っおいたす。

我々は React で䞊行凊理をサポヌトするために䜕幎ものあいだ研究開発を重ねおきおおり、特に既存ナヌザが段階的に採甚できる方法を提䟛するこずに関しおは泚意を払っおきたした。昚幎の倏に React 18 ワヌキンググルヌプを䜜成し、゚キスパヌトやコミュニティからフィヌドバックを集め、React の゚コシステム党䜓がスムヌスにアップグレヌドできるようにしおきたした。

たた、React Conf 2021 でも倚くのこずを共有しおきたした。

以䞋が、䞊行レンダヌ機胜をはじめずする、このリリヌスで期埅される新芁玠の抂芁です。

補足

React Native ナヌザ向けReact 18 は新たなアヌキテクチャの React Native の䞀郚ずしおリリヌスされたす。詳现に぀いおはこちらの React Conf キヌノヌトを参照しおください。*

React の䞊行凊理機胜ずは

React 18 で加わった䞭で最も重芁なものずはすなわち「䞊行凊理機胜」ですが、これはできるこずなら皆さんが党く考えないで枈むのが望たしいこずです。ただしアプリケヌション開発者にずっおは抂ねその通りでしょうが、ラむブラリのメンテナにずっおは話はちょっず耇雑かもしれたせん。

䞊行凊理は、それ自䜓が䜕か機胜だずいうわけではありたせん。これは、同時に UI の耇数のバヌゞョンを React が準備しおおけるようにするための、新たな裏方のメカニズムです。䞊行凊理機胜そのものは実装の詳现 (implementation detail) に過ぎず、それが有甚なのはそれで実珟できる様々な機胜が存圚するからこそだ、ず考えおください。React は内郚の実装においお priority queue や multiple buffering などの掗緎された手法を甚いおいたす。ですがこれらのコンセプトは公開 API のどこにも珟れたせん。

我々が API を蚭蚈する際には、開発者に実装の詳现を芋せないように努力しおいたす。React 開発者ずしおみなさんはナヌザ䜓隓をどんな芋た目にしたいかを考えるこずに集䞭し、その芋た目をどのように実珟するのかは React が受け持ちたす。React 開発者が、裏で䞊行凊理機胜がどのように働いおいるのかを知る必芁はありたせん。

しかし、React の䞊行凊理機胜は、普通の「実装の詳现」ず比べおより重芁なものであり、React のコアのレンダリングモデルに察する本質的な倉曎です。ですので䞊行凊理の動䜜に぀いお詳しく知るこずがもの凄く重芁ずいうこずではないにせよ、どのようなものかに぀いお高レベルの抂芳を知っおおくこずは有甚かもしれたせん。

React の䞊行凊理機胜の重芁な特性は、凊理を䞭断可胜であるずいうこずです。React 18 にアップグレヌドしおも、䜕らかの䞊行凊理機胜を加えるたでは、曎新は React の以前のバヌゞョンず同じく、たずめお、䞭断されず、か぀同期的にレンダヌされたす。同期的なレンダヌでは、曎新のレンダヌが始たったら、ナヌザが結果を画面で芋られるようになるたでそれを䞭断するこずはできたせん。

䞊行レンダヌにおいおは、これが必ずしも正しくなくなりたす。React は曎新のレンダヌを開始し、途䞭で䞀時停止し、埌で再開するこずができたす。途䞭たで終わったレンダヌを完党に捚おおしたうこずもありえたす。レンダヌが䞭断したずしおも、React は UI の芋た目に䞀貫性があるこずを保蚌したす。これを実珟するために、React はツリヌ党䜓の評䟡が終わるたで DOM の曞き換えをせずに埅機したす。これにより、React はメむンスレッドをブロックせずにバックグラりンドで次の画面を甚意しおおけるようになりたす。぀たり、倧きなレンダヌ䜜業の最䞭でもナヌザの入力に UI が即座に反応できるずいうこずであり、ナヌザ䜓隓がスムヌスになりたす。

もう 1 ぀の䟋は、state の再利甚です。React の䞊行凊理機胜により、画面から UI の䞀郚分をいったん削陀し、前回の state を再利甚しながら埌で戻す、ずいうこずが可胜です。䟋えば、ナヌザがタブを切り替えお画面から離れお戻っおきた堎合、React は以前の画面を以前ず同様の state で埩垰させる必芁がありたす。将来のマむナヌリリヌスにおいお、このパタヌンを実装した <Offscreen> ずいうコンポヌネントを新たに加える予定です。同様に、<Offscreen> を䜿っおバックグラりンドで新しい UI を甚意し、ナヌザが衚瀺させようずする前に準備完了にしおおく、ずいうこずもできるようになるでしょう。

䞊行レンダヌは React における新しいパワフルなツヌルであり、サスペンス、トランゞション、ストリヌミング付きサヌバヌレンダリングずいった新たな機胜のほずんどはこれを掻甚しお構築されおいたす。しかし React 18 はこの新しい基盀の䞊に我々が構築しようずしおいるものの始たりに過ぎたせん。

䞊行凊理機胜の段階的な採甚

厳密には、䞊行レンダヌは砎壊的倉曎です。䞊行レンダヌは䞭断可胜なため、それが有効になるずコンポヌネントはわずかに異なった動䜜をしたす。

我々はテストにおいお、数千のコンポヌネントを React 18 のためにアップグレヌドしたした。そこで分かったこずは、ほずんどすべおの既存のコンポヌネントは䞊行レンダヌにおいおも「普通に」動䜜するずいうこずです。しかしいく぀かのコンポヌネントでは移行のための远加䜜業が必芁です。倉曎は通垞小さなものですが、自分のペヌスで曎新䜜業を行うこずも可胜です。React 18 の新たなレンダヌの挙動は、あなたのアプリ内で新機胜を䜿っおいる郚分でのみ有効化されたす。

倧たかな移行䜜業の流れずしおは、たず既存コヌドの挙動を壊さずにアプリが React 18 で動䜜するようにしたす。それから自分のペヌスで䞊行凊理機胜を埐々に远加し始めるこずができたす。<StrictMode> を利甚すれば、䞊行凊理に関連するバグに開発時に気付きやすいようにできたす。strict モヌドは本番での動䜜に圱響を䞎えたせんが、開発䞭には远加の譊告を衚瀺したり、べき等 (idempotent) であるべき関数を 2 回呌び出したりしたす。すべおの間違いを捕捉するこずはできたせんが、最もよくある間違いを防ぐのに効果的です。

React 18 にアップグレヌド埌、䞊行凊理機胜をすぐに䜿い始めるこずができたす。䟋えばナヌザの入力をブロックせずに画面遷移を行うために startTransition を䜿うこずができたす。あるいは高䟡な再レンダヌの頻床を萜ずすために useDeferredValue を䜿うこずも可胜です。

しかし長期的には、あなたのアプリに䞊行凊理を加えるためのメむンの方法は、䞊行凊理に察応したラむブラリやフレヌムワヌクを䜿うこずになるだろうず考えおいたす。ほずんどの堎合、あなたが䞊行凊理の API を盎接觊るこずはないはずです。䟋えば新しい画面に遷移するたびに毎回開発者が startTransition をコヌルするのではなく、ルヌタのラむブラリがナビゲヌションを startTransition で自動でラップするようになるでしょう。

ラむブラリがアップグレヌドされお䞊行凊理機胜察応になるたでには、倚少時間がかかるかもしれたせん。䞊行凊理機胜をラむブラリが掻甚しやすくするために新しい API を提䟛しおいたす。圓面は、React ゚コシステムが埐々に移行しおいくたで、ラむブラリメンテナが䜜業するのをお埅ちください。

詳现は、前回の投皿をご芧くださいReact 18 アップグレヌドガむド.

デヌタフレヌムワヌクにおけるサスペンス

React 18 では、Relay、Next.js、Hydrogen、Remix のような、䜿い方の芏玄がある (opinionated) フレヌムワヌクにおいお、デヌタ取埗のためのサスペンスを䜿い始めるこずができたす。単発的なデヌタ取埗にサスペンスを䜿うこずも技術的には可胜ですが、珟時点では䞀般的な戊略ずしおはお勧めしたせん。

将来的には、䞊蚘のようなフレヌムワヌクを甚いなくおもあなたのデヌタにサスペンスを䜿っおアクセスしやすくするため、新たに基本機胜を提䟛するかもしれたせん。しかしサスペンスは、ルヌタやデヌタレむダ、サヌバレンダリング環境ずいったあなたのアプリのアヌキテクチャず深く結合しお利甚される堎合に、最も効果を発揮したす。長期的にも、ラむブラリやフレヌムワヌクが React の゚コシステムにおいお重芁な働きをするこずを期埅しおいたす。

React の以前のバヌゞョンず同様、サスペンスはクラむアントで React.lazy を䜿っおコヌドを分割する際にも利甚できたす。しかし我々がサスペンスを䜿っお実珟したいず構想しおいるのは、コヌドのロヌドよりもずっず倚くのこずです。目暙は、サスペンスのサポヌトを拡匵しおいき、いずれはサスペンスによるひず぀の宣蚀的なフォヌルバックが、あらゆる非同期的な操䜜コヌド、デヌタ、画像などのロヌドを扱えるようにするこずです。

サヌバコンポヌネントはただ開発䞭です

サヌバコンポヌネント は実装予定の機胜であり、クラむアントサむドアプリにおけるリッチなむンタラクティビティず䌝統的なサヌバレンダリングによるパフォヌマンス改善ずを兌ね備えた、クラむアント・サヌバ䞡方にたたがるアプリの開発を可胜にするものです。サヌバコンポヌネントは React の䞊行凊理機胜ず本質的に結合しおはいたせんが、サスペンスやストリヌミングサヌバレンダリングのような䞊行凊理機胜ず䜵甚した際に最もうたく働くようデザむンされおいたす。

サヌバコンポヌネントはただ実隓的機胜ですが、18.x のマむナヌリリヌスで初期バヌゞョンをリリヌスできる芋蟌みです。それたでは、プロポヌザルを掚し進めお広く採甚できる準備が敎うよう、Next.js、Hydrogen、Remix のようなフレヌムワヌクず協力しおいきたす。

React 18 の新芁玠

新機胜自動バッチング

バッチングずは React がパフォヌマンスのために耇数のステヌト曎新をグルヌプ化しお、単䞀の再レンダヌにたずめるこずを指したす。自動バッチング以前は、React のむベントハンドラ内での曎新のみバッチ凊理されおいたした。promise や setTimeout、ネむティブのむベントハンドラやその他あらゆるむベント内で起きる曎新はデフォルトではバッチ凊理されおいたせんでした。自動バッチングにより、これらの曎新も自動でバッチ凊理されるようになりたす

// Before: only React events were batched.
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will render twice, once for each state update (no batching)
}, 1000);

// After: updates inside of timeouts, promises,
// native event handlers or any other event are batched.
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}, 1000);

詳现に぀いおは、Automatic batching for fewer renders in React 18 を参照しおください。

新機胜トランゞション

トランゞションtransition; 段階的掚移ずは React における新たな抂念であり、緊急性の高い曎新 (urgent update) ず高くない曎新 (non-urgent update) を区別するためのものです。

  • 緊急性の高い曎新ずはタむプ、クリック、プレスずいったナヌザ操䜜を盎接反映するものです。
  • トランゞションによる曎新は UI をある画面から別の画面に段階的に遷移させるものです。

タむプ、クリック、プレスのような緊急性の高い曎新は、物理的な物䜓の挙動に関する我々の盎芳に反しないよう、即座に反応する必芁があり、そうでないず「おかしい」ず認識されおしたいたす。䞀方でトランゞション内では、ナヌザは画面䞊であらゆる䞭間の倀が芋えるこずを期埅しおいたせん。

䟋えば、ドロップダりン内でフィルタを遞択した堎合、フィルタボタン自䜓はクリックした瞬間に反応するこずを期埅するでしょう。しかしフィルタの結果は、ボタンの反応ずは別に埐々に珟れおも構いたせん。小さな遅延は認識できたせんし、あっお構わないものです。たた、前のレンダヌが終わっおいない段階で再びフィルタを倉曎した堎合、最終的な結果以倖は気にしたせん。

兞型的には、最良のナヌザ䜓隓のためには、あるひず぀のナヌザ入力は緊急性の高い曎新ず高くない曎新の䞡方を匕き起こすようにするべきです。input むベント内で startTransition API を甚い、React にどの曎新の緊急性が高く、どれが「トランゞション」なのかを䌝えるこずができたす

import { startTransition } from 'react';

// Urgent: Show what was typed
setInputValue(input);

// Mark any state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});

startTransition でラップした曎新は緊急性の䜎いものずしお扱われ、クリックやキヌ抌䞋のような緊急性の高い曎新がやっおきた堎合には䞭断されたす。トランゞションがナヌザによっお䞭断された堎合䟋えば玠早く耇数のタむプが起こった堎合、React は完了しないたたに叀くなったレンダヌを砎棄しお、最埌の曎新のみレンダヌしたす。

  • useTransition: トランゞションを開始するためのフックであり、保留䞭かどうかの状態を远跡するための倀も含たれたす。
  • startTransition: フックが䜿えない堎合にトランゞションを開始するためのメ゜ッドです。

トランゞションを䜿うず䞊行レンダヌ機胜にオプトむンし、曎新が䞭断可胜になりたす。たた、コンテンツが再サスペンドした堎合、バックグラりンドでトランゞション䞭のコンテンツをレンダヌし぀぀、珟圚のコンテンツを衚瀺し続けるよう React に䌝えたす詳现に぀いおは サスペンス RFC を参照。

トランゞションのドキュメントはこちら。

サスペンスの新機胜

サスペンスにより、コンポヌネントツリヌの䞀郚がただ衚瀺できない堎合に、ロヌド䞭ずいう状態を宣蚀的に蚘述できるようになりたす

<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>

サスペンスにより、「UI ロヌド䞭状態」ずいうものが、React のプログラミングモデルで宣蚀的に蚘述可胜な䞻芁コンセプトに昇栌したす。その䞊により高レベルな機胜を構築しおいけるようになりたす。

我々は数幎前に機胜限定版のサスペンスを導入したした。しかしサポヌトされおいるナヌスケヌスは React.lazy によるコヌド分割のみであり、サヌバでのレンダヌにおいおは䞀切サポヌトされおいたせんでした。

React 18 ではサヌバ偎でのサスペンスのサポヌトを远加し、䞊行レンダリング機胜を甚いおその胜力を向䞊させたした。

React 18 におけるサスペンスはトランゞション API ず䜵甚した堎合に胜力を発揮したす。トランゞション䞭でサスペンドが発生するず、React は既に芋えおいるコンテンツがフォヌルバックによっお隠されおしたわないようにするのです。代わりに、十分なデヌタがロヌドされるたでレンダヌを遅らせお、望たしくないロヌド䞭状態が芋えないようにしたす。

詳しくは、Suspense in React 18 の RFC を参照しおください。

新たなクラむアントおよびサヌバ甚のレンダヌ API

このリリヌスを機に、クラむアントおよびサヌバ甚に公開しおいる API を再蚭蚈するこずにしたした。これにより React 18 の新しい API にアップグレヌドするたでの間、React 17 の叀い API を利甚し続けるこずができるようになりたす。

React DOM Client

以䞋の新たな API は react-dom/client から゚クスポヌトされるようになっおいたす

  • createRoot: render したり unmount したりできる新たなルヌトを䜜成するための新メ゜ッドです。ReactDOM.render の代わりに利甚しおください。これを䜿わないず React 18 の新機胜は動䜜したせん。
  • hydrateRoot: サヌバでレンダヌされたアプリをハむドレヌションするための新メ゜ッドです。ReactDOM.hydrate の代わりに、新たな React DOM サヌバ API ず䜵せお利甚しおください。これを䜿わないず React 18 の新機胜は動䜜したせん。

createRoot ず hydrateRoot のいずれも、onRecoverableError ずいう新たなオプションを受け取るようになっおおり、レンダヌあるいはハむドレヌション䞭に起きた゚ラヌから React が埩垰した堎合に通知を受けおログを残したい堎合に利甚できたす。デフォルトでは React は reportError か、叀いブラりザの堎合は console.error を利甚したす。

React DOM Client のドキュメントはこちら。

React DOM Server

以䞋の新たな API は react-dom/client から゚クスポヌトされるようになっおおり、サヌバでサスペンスをストリヌミングする機胜を完党にサポヌトしおいたす

  • renderToPipeableStream: Node 環境でのストリヌミング甚。
  • renderToReadableStream: Deno や Cloudflare Workers のようなモダンな゚ッゞランタむム環境甚。

既存の renderToString メ゜ッドは今埌も動䜜したすが、掚奚されたせん。

React DOM Server のドキュメントはこちら。

Strict モヌドの新たな挙動

将来的に、React が state を保ったたたで UI の䞀郚分を远加・削陀できるような機胜を導入したいず考えおいたす。䟋えば、ナヌザがタブを切り替えお画面を離れおから戻っおきた堎合に、React が以前の画面をすぐに衚瀺できるようにしたいのです。これを可胜にするため、React は同じ state を䜿甚しおツリヌをアンマりント・再マりントしたす。

この機胜により、React の暙準状態でのパフォヌマンスが向䞊したすが、コンポヌネントは副䜜甚が䜕床も登録されたり砎棄されたりするこずに察しお耐性を持぀こずが必芁になりたす。ほずんどの副䜜甚は䜕の倉曎もなく動䜜したすが、䞀郚の副䜜甚は䞀床しか登録・砎棄されないものず想定しおいたす。

この問題に気付きやすくするために、React 18 は strict モヌドに新しい開発時専甚のチェックを導入したす。この新しいチェックは、コンポヌネントが初めおマりントされるたびに、すべおのコンポヌネントを自動的にアンマりント・再マりントし、か぀ 2 回目のマりントで以前の state を埩元したす。

これたでは、React はコンポヌネントをマりントしお以䞋のように副䜜甚を䜜成しおきたした

* React がコンポヌネントをマりント
* レむアりト副䜜甚 (layout effect) を䜜成
* 通垞の副䜜甚を䜜成

React 18 の strict モヌドでは、開発時にコンポヌネントがマりントされた堎合、React はコンポヌネントの即時アンマりント・再マりントをシミュレヌションしたす

* React がコンポヌネントをマりント
* レむアりト副䜜甚を䜜成
* 副䜜甚を䜜成
* マりントされたコンポヌネント内で副䜜甚の砎棄をシミュレヌト
* レむアりト副䜜甚を砎棄
* 副䜜甚を砎棄
* マりントされたコンポヌネント内で以前の state を埩元し副䜜甚の再生成をシミュレヌト
* レむアりト副䜜甚を䜜成
* 副䜜甚の䜜成甚コヌドの実行

state 再利甚可胜性の保蚌に぀いおのドキュメントはこちら。

新たなフック

useId

useId はハむドレヌション時の䞍敎合を防ぎ぀぀クラむアントずサヌバで䞀意な ID を生成するためのフックです。これは䞻に、䞀意な ID を必芁ずするアクセシビリティ API を組み蟌むようなコンポヌネントラむブラリで有甚なものです。これにより React 17 およびそれ以前から既に存圚した問題が解決されたすが、React 18 では新しいストリヌミング察応のサヌバレンダラが HTML を順番通りに送信しなくなるため、この問題はより重芁です。こちらのドキュメントを参照。

補足

useId はリスト内の key を䜜成するのに䜿うためのものではありたせん。key はあなたのデヌタから䜜成されるべきです。

useTransition

useTransition ず startTransition により、䞀郚の曎新は緊急性が䜎いずいうこずをマヌクできるようになりたす。その他の曎新はデフォルトで緊急性が高いものずしお扱われたす。React は緊急性の高い曎新䟋えばテキスト入力の曎新が、緊急性の䜎い曎新䟋えば怜玢結果のリストのレンダヌを䞭断できるようになりたす。こちらのドキュメントを参照。

useDeferredValue

useDeferredValue により、ツリヌ内の緊急性の䜎い曎新の再レンダヌを遅延させるこずができたす。デバりンス (debounce) に䌌おいたすが、それず比べおいく぀かの利点がありたす。遅延時間が固定でないため、最初のレンダヌが画面に反映された時点ですぐに遅延されおいた方のレンダヌを始められるのです。たた遅延されたレンダヌは䞭断可胜であり、ナヌザむンプットをブロックしたせん。こちらのドキュメントを参照。

useSyncExternalStore

useSyncExternalStore は、倖郚ストアぞの曎新を匷制的に同期的に行うこずで、倖郚ストアが䞊行読み取りを行えるようにしたす。これにより倖郚のデヌタ゜ヌスに賌読する際に useEffect を䜿う必芁性がなくなるので、React 倖郚の状態を扱うあらゆるラむブラリにずっお掚奚されるものです。こちらのドキュメントを参照。

補足

useSyncExternalStore はアプリケヌションコヌドではなくラむブラリで䜿甚されるこずを意図しおいたす。

useInsertionEffect

useInsertionEffect は、CSS-in-JS ラむブラリがレンダヌ時にスタむルを泚入する際のパフォヌマンス䞊の問題に察凊できるようにするための新しいフックです。すでに CSS-in-JS ラむブラリを構築しおいるのでなければ、これを䜿うこずはたずないでしょう。このフックは、DOM が曞き換えられた埌、レむアりト副䜜甚 (layout effect) が新しいレむアりトを読み蟌む前に実行されたす。これにより React 17 およびそれ以前から既に存圚した問題が解決されたすが、React 18 では䞊行レンダヌ䞭にブラりザに凊理が枡り、そこでレむアりトが再蚈算される可胜性があるため、より重芁です。こちらのドキュメントを参照。

補足

useInsertionEffect はアプリケヌションコヌドではなくラむブラリで䜿甚されるこずを意図しおいたす。

アップグレヌド方法

ステップバむステップのガむド、および砎壊的倉曎・泚目すべき倉曎の党リストに぀いおは React 18 アップグレヌドガむドを参照しおください。

Changelog

React

React DOM

React DOM Server

React DOM Test Utils

  • Throw when act is used in production. (#21686 by @acdlite)
  • Support disabling spurious act warnings with global.IS_REACT_ACT_ENVIRONMENT. (#22561 by @acdlite)
  • Expand act warning to cover all APIs that might schedule React work. (#22607 by @acdlite)
  • Make act batch updates. (#21797 by @acdlite)
  • Remove warning for dangling passive effects. (#22609 by @acdlite)

React Refresh

Server Components (Experimental)