React v17.0
日本語版サイトでは英語版ブログに定期的に追従しつつ、2020 年以降の記事を随時翻訳しています。
このブログはアーカイブされています。最新の記事は ja.react.dev/blog でご覧ください。
本日、React 17 をリリースします! React 17 リリースの役割や含まれている変更点については React 17 RC のブログ記事で詳しく述べてあります。この記事はそちらの短いサマリとなりますので、RC の記事を既に読んでいる場合は、本記事は飛ばして構いません。
新機能 “なし”
この React 17 リリースは普段のリリースと異なっており、開発者向けの新機能が何も追加されていません。代わりに、このリリースは React 自体のアップグレードを簡単にすることに焦点を当てています。
具体的には React 17 は、あるバージョンの React で管理されるツリー内に、別のバージョンの React で管理されるツリーをより安全に埋め込めるようにするための、「踏み台」となるリリースとなっています。
また、他のテクノロジによって構築されているアプリ内に React を埋め込むことも容易になります。
段階的なアップグレード
React 17 は段階的な React のアップグレードを可能にします。React 15 から 16 に(そして今回は React 16 から 17 に)アップグレードする場合、普通はアプリ全体をまとめてアップグレードします。これは多くのアプリではうまく行きます。しかしコードが数年以上前に書かれており活発にメンテされていないような場合、だんだんと難易度が増していきます。ページ内で 2 つの React のバージョンを混在させることは可能ですが、React 17 以前にこのようなことをすると不安定になり、イベント絡みの問題が引き起こされていました。
React 17 で、これらの問題の多くを修正します。これは React 18 やもっと将来のバージョンが来たときに、とれる選択肢が増えるということを意味します。選択肢のひとつは、これまでやってきたのと同様、アプリ全体を一度にアップグレードするというものです。しかし今後は、アプリを一部分ずつアップグレードするという選択肢がとれるようになります。例えば、アプリの大部分を React 18 に移行しつつ、いくつかの遅延ロードされるダイアログやサブページを React 17 のままにしておけるようになります。
だからといって段階的に更新しないといけないという訳ではありません。今後もほとんどのアプリでは、一気にアップグレードするのがベストの選択肢です。2 つのバージョンの React をロードするというのは、たとえ片方はオンデマンドで遅延ロードするのだとしても、やはり理想的ではありません。しかし、活発にメンテされていない大きなアプリではこの選択肢は検討に値するものであり、React 17 はこのようなアプリが取り残されずに済むようにします。
古いバージョンの React を必要に応じて遅延ロードするという手法をデモするためのサンプルリポジトリを用意しました。このデモは Create React App を使っていますが、他のどのようなツールでも似たアプローチが可能なはずです。他のツールを使ったデモを追加するプルリクエストを歓迎します。
補足
その他の変更は React 17 より後に延期しました。このリリースの目標は段階的なアップグレードを可能にすることです。React 17 自体へのアップグレードが難しいようでは本リリースの目的が台無しですので、そのようなことはないはずです。
イベントデリゲーションに関する変更
段階的なアップグレードを可能にするために、React のイベントシステムに幾つかの変更を加える必要がありました。React 17 がメジャーリリースとなっているのは、これらの変更が一部互換性の問題を引き起こす可能性があるからです。我々の安定性に対する取り組みについてはバージョニングについての FAQ で読むことができます。
React 17 では、React は裏で document
のレベルにイベントハンドラをアタッチしないようになります。代わりに、あなたが React ツリーをレンダーしようとしているルート DOM コンテナに対してアタッチするようになります:
const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);
React 16 およびそれ以前では、React はほとんどのイベントに対して document.addEventListener()
のようにしていました。代わりに React 17 は、水面下で rootNode.addEventListener()
という呼び出しを行うようになります。
この新しい挙動により、React コードと非 React コードの統合に関して 過去 数年に わたって 報告 されて きた 様々な 問題が 解決 される ことが分かっています。
この変更により問題が出た場合は、こちらによくある解決法が載っています。
その他の破壊的変更
React 17 RC のブログ記事 に React 17 におけるその他の破壊的変更について説明があります。
Facebook のプロダクトコードにおける 10 万を超えるのコンポーネントのうち、これらの変更に対応するために変更する必要があったのは 20 未満でしたので、ほとんどのアプリは React 17 にトラブルなく移行できると考えています。問題があった場合は知らせてください。
新しい JSX トランスフォーム
Raect 17 は新しい JSX トランスフォームをサポートします。このサポートは React 16.14.0、React 15.7.0、React 0.14.10 にもバックポートされています。これは完全にオプトインであり、使う必要はないということに留意してください。以前の JSX トランスフォームも動作し続けますし、サポートを終了する予定はありません。
React Native
React Native のリリーススケジュールは React と異なっています。React 17 へのサポートは React Native 0.64 にて追加されました。いつものように、リリースに関する議論は React Native Community のリリースに関するイシュートラッカで追うことができます。
インストール
React 17 を npm でインストールするには以下のようにします:
npm install react@17.0.0 react-dom@17.0.0
React 17 を Yarn でインストールするには以下のようにします:
yarn add react@17.0.0 react-dom@17.0.0
CDN 経由で React の UMD ビルドも提供しています:
<script crossorigin src="https://unpkg.com/react@17.0.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17.0.0/umd/react-dom.production.min.js"></script>
詳細なインストール手順についてはドキュメントを参照してください。
Changelog
React
- Add
react/jsx-runtime
andreact/jsx-dev-runtime
for the new JSX transform. (@lunaruan in #18299) - Build component stacks from native error frames. (@sebmarkbage in #18561)
- Allow to specify
displayName
on context for improved stacks. (@eps1lon in #18224) - Prevent
'use strict'
from leaking in the UMD bundles. (@koba04 in #19614) - Stop using
fb.me
for redirects. (@cylim in #19598)
React DOM
- Delegate events to roots instead of
document
. (@trueadm in #18195 and others) - Clean up all effects before running any next effects. (@bvaughn in #17947)
- Run
useEffect
cleanup functions asynchronously. (@bvaughn in #17925) - Use browser
focusin
andfocusout
foronFocus
andonBlur
. (@trueadm in #19186) - Make all
Capture
events use the browser capture phase. (@trueadm in #19221) - Don’t emulate bubbling of the
onScroll
event. (@gaearon in #19464) - Throw if
forwardRef
ormemo
component returnsundefined
. (@gaearon in #19550) - Remove event pooling. (@trueadm in #18969)
- Stop exposing internals that won’t be needed by React Native Web. (@necolas in #18483)
- Attach all known event listeners when the root mounts. (@gaearon in #19659)
- Disable
console
in the second render pass of DEV mode double render. (@sebmarkbage in #18547) - Deprecate the undocumented and misleading
ReactTestUtils.SimulateNative
API. (@gaearon in #13407) - Rename private field names used in the internals. (@gaearon in #18377)
- Don’t call User Timing API in development. (@gaearon in #18417)
- Disable console during the repeated render in Strict Mode. (@sebmarkbage in #18547)
- In Strict Mode, double-render components without Hooks too. (@eps1lon in #18430)
- Allow calling
ReactDOM.flushSync
during lifecycle methods (but warn). (@sebmarkbage in #18759) - Add the
code
property to the keyboard event objects. (@bl00mber in #18287) - Add the
disableRemotePlayback
property forvideo
elements. (@tombrowndev in #18619) - Add the
enterKeyHint
property forinput
elements. (@eps1lon in #18634) - Warn when no
value
is provided to<Context.Provider>
. (@charlie1404 in #19054) - Warn when
memo
orforwardRef
components returnundefined
. (@bvaughn in #19550) - Improve the error message for invalid updates. (@JoviDeCroock in #18316)
- Exclude forwardRef and memo from stack frames. (@sebmarkbage in #18559)
- Improve the error message when switching between controlled and uncontrolled inputs. (@vcarl in #17070)
- Keep
onTouchStart
,onTouchMove
, andonWheel
passive. (@gaearon in #19654) - Fix
setState
hanging in development inside a closed iframe. (@gaearon in #19220) - Fix rendering bailout for lazy components with
defaultProps
. (@jddxf in #18539) - Fix a false positive warning when
dangerouslySetInnerHTML
isundefined
. (@eps1lon in #18676) - Fix Test Utils with non-standard
require
implementation. (@just-boris in #18632) - Fix
onBeforeInput
reporting an incorrectevent.type
. (@eps1lon in #19561) - Fix
event.relatedTarget
reported asundefined
in Firefox. (@claytercek in #19607) - Fix “unspecified error” in IE11. (@hemakshis in #19664)
- Fix rendering into a shadow root. (@Jack-Works in #15894)
- Fix
movementX/Y
polyfill with capture events. (@gaearon in #19672) - Use delegation for
onSubmit
andonReset
events. (@gaearon in #19333) - Improve memory usage. (@trueadm in #18970)
React DOM Server
- Make
useCallback
behavior consistent withuseMemo
for the server renderer. (@alexmckenley in #18783) - Fix state leaking when a function component throws. (@pmaccart in #19212)
React Test Renderer
- Improve
findByType
error message. (@henryqdineen in #17439)
Concurrent Mode (Experimental)
- Revamp the priority batching heuristics. (@acdlite in #18796)
- Add the
unstable_
prefix before the experimental APIs. (@acdlite in #18825) - Remove
unstable_discreteUpdates
andunstable_flushDiscreteUpdates
. (@trueadm in #18825) - Remove the
timeoutMs
argument. (@acdlite in #19703) - Disable
<div hidden />
prerendering in favor of a different future API. (@acdlite in #18917) - Add
unstable_expectedLoadTime
to Suspense for CPU-bound trees. (@acdlite in #19936) - Add an experimental
unstable_useOpaqueIdentifier
Hook. (@lunaruan in #17322) - Add an experimental
unstable_startTransition
API. (@rickhanlonii in #19696) - Using
act
in the test renderer no longer flushes Suspense fallbacks. (@acdlite in #18596) - Use global render timeout for CPU Suspense. (@sebmarkbage in #19643)
- Clear the existing root content before mounting. (@bvaughn in #18730)
- Fix a bug with error boundaries. (@acdlite in #18265)
- Fix a bug causing dropped updates in a suspended tree. (@acdlite in #18384 and #18457)
- Fix a bug causing dropped render phase updates. (@acdlite in #18537)
- Fix a bug in SuspenseList. (@sebmarkbage in #18412)
- Fix a bug causing Suspense fallback to show too early. (@acdlite in #18411)
- Fix a bug with class components inside SuspenseList. (@sebmarkbage in #18448)
- Fix a bug with inputs that may cause updates to be dropped. (@jddxf in #18515 and @acdlite in #18535)
- Fix a bug causing Suspense fallback to get stuck. (@acdlite in #18663)
- Don’t cut off the tail of a SuspenseList if hydrating. (@sebmarkbage in #18854)
- Fix a bug in
useMutableSource
that may happen whengetSnapshot
changes. (@bvaughn in #18297) - Fix a tearing bug in
useMutableSource
. (@bvaughn in #18912) - Warn if calling setState outside of render but before commit. (@sebmarkbage in #18838)