Reactチームは、React 16の2年後にReact 17(最初のリリース候補版)を最近リリースした。React 17は、2つの同時バージョンが共存できるようにすることで、Reactの将来のメジャーバージョン間の移行が簡単になるよう努めている。React 17には、イベントシステムとスケジューリングに関連するいくつかの重大な変更が加えられている。
Reactのリリースノートでは、React 17の背景にある主要な推進要因について説明している。
React 17リリースは、主にReact自体のアップグレードを容易にすることに重点を置いています。
[…] React 17リリースは、誰も置き去りにすることなく[新しいReact機能]を展開するという私たちの戦略の重要な部分です。
特に、React 17は「足がかり」のリリースであり、あるバージョンのReactで管理されているツリーを、別のバージョンのReactで管理されているツリー内に安全に埋め込むことができる。[…]他の変更はReact 17の後に延期しました。
React 17では段階的なReactアップグレードが可能となる。Reactの新しいバージョンがリリースされると、開発者はReactアプリケーションを一度に移行するか(以前のバージョンのReactの場合)、あるいは、アプリケーションの一部をアップグレードして徐々に完了するかを選択できる。後者のオプションでは、ユーザーエクスペリエンスに影響を与えないように、2つのReactバージョンのいずれかを遅延ロードできる。
異なるReactバージョンの共存は、イベント移譲メカニズムの変更によって実現している。React 17の前は、Reactはdocument
レベルでイベントハンドラを登録し、呼び出すコンポーネントを検出し、コンポーネントツリー全体で後続のイベントバブリングを処理していた。つまり、2つのReactバージョンは基本的に共有DOM状態(DOMイベント処理の状態)に同時にアクセスしており、Reactの合成イベント(コピー)とDOMイベント(本当のソース)の間の同期メカニズムはない。したがって、1つのReactバージョンが(コピー)DOMイベント伝播(event.stopPropagation()
)をキャンセルすると、そのキャンセルが他のReactバージョン(2番目のコピー)に通知されない可能性がある。これにより、キャンセルされたイベントに反応する可能性がある。また、最上位に登録されているイベントハンドラが不幸な順序で実行される可能性もある。
React 17は、ReactバージョンのルートDOMコンテナ(以降はrootNode
)にイベントハンドラをアタッチする。
const rootNode = document.getElementById('root'); ReactDOM.render(<App />, rootNode);
同様に、Reactは、DOMの一部を処理する他のJavaScriptライブラリとより確実に相互運用できるようになった。実際のところ、Reactのイベント伝播メカニズムの変更により、いくつかの古いバグが修正されている。
他の重大な変更の中でも、onScroll
イベントはバブルではなくなり、onFocus
イベントとonBlur
イベントはネイティブのfocusin
とfocusout
を使用し、キャプチャフェーズイベント(onClickCapture
など)は実際のブラウザキャプチャフェーズリスナーを使用するようになった。この変更により、DOMイベントとReact合成イベントの間の相違が低減する。
React 17では、useEffect
フックに対してスケジューリングの変更がある。React 16では、同期的に実行されていたエフェクトのcleanup機能が、非同期で実行されるようになった。React 17はさらに、ツリー内の位置に応じて、エフェクトと同じ順序でクリーンアップ機能を実行する。スケジューリングの変更により、一部のコンポーネントが壊れた。リリースノートには、潜在的な問題と解決策に関する詳細が追記されている。
開発者はnpmを使用してリリース候補版をインストールできる。
npm install react@17.0.0-rc.0 react-dom@17.0.0-rc.0
リリースノートには、完全な変更リスト(Changelog)と、主な変更の背後にある動機の詳細が記載されている。