はじめに
Reactは、動的なWebページのインターフェースを構築するためのJavaScriptライブラリーで、Facebookとオープンソースコミュニティによって開発が続けられています。
Reactは2022年3月にメジャーアップデートであるバージョン18(以下「React 18」がリリースされ、現在の最新バージョンは18.2.0です。React 18の概要は公式ブログ記事で紹介されています。
本記事では、前回に引き続き、React 18で導入された改良や新機能を紹介します。
対象読者
- 新バージョンでReactを体験してみたい方
- すでにReact開発に従事していて、新機能を知りたい方
- Reactの最新動向を追っておきたい方
必要な環境
本記事のサンプルコードは、以下の環境で動作を確認しています。
- Windows 10 64bit版
- React 18.2.0
- Node.js v18.16.1
- Microsoft Edge 114.0.1823.67
サンプルコードを実行するには、サンプルのフォルダーで「npm install」コマンドを実行してライブラリーをダウンロード後「npm run start」コマンドを実行して、「http://localhost:3000」をWebブラウザーで表示します。本記事内ではReact 18の新機能に関する本質的な部分を抽出して説明するので、それ以外の実装は各サンプルコードを参照してください。
潜在的な問題点を洗い出すStrictモードへの機能追加
ReactのStrictモードは、開発中にアプリケーションの潜在的な問題点を洗い出すツールです。React 18ではこのStrictモードに機能が追加されました。
Reactの将来バージョンでは、より効率の良い表示を行うため、同じ状態(ステート)を保ったままコンポーネントを非表示(アンマウント)、再表示(再マウント)できるようになる予定です。この場合コンポーネントでは、表示・非表示時に実行される追加処理(「副作用」と呼ばれます)が複数回実行されても大丈夫なようにしておく必要があります。この確認のため、React 18のStrictモードでは、すべてのコンポーネントを表示する際に、内部的に「マウント→アンマウント→再マウント」と実行されるようになります。
Strictモードは、適用する場所を<React.StrictMode>タグで囲むことで利用できます。ReactのCLI「create-react-app」で生成したプロジェクトでは既定で、Webページ全体のコンポーネント(Appコンポーネント)にStrictモードが適用されています(リスト1)。
const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> {/* Strictモードここから */} <App /> </React.StrictMode> {/* Strictモードここまで */} );
Strictモードの動作を、図3のサンプルで表示します。このサンプルはStrictモードで実行すると、リストに同じ文言が2行表示されますが、Strictモードを解除すると1行だけ表示されます。
図3のサンプルのAppコンポーネントはリスト2の通りです。
function App() { useEffect(() => { // 副作用の実行 ...(1) console.log('副作用の実行'); // 副作用が1回だけ実行されることを意図した処理 ...(1a) // 複数回実行されるとつじつまが合わない const li = document.createElement('li'); li.textContent='Galaxy S23 Ultra'; document.getElementById('effect-area').appendChild(li); return () => { // クリーンアップの処理 ...(2) console.log('クリーンアップ') // 複数回実行に対応するためのクリーンアップ ...(2a) // const elem = document.getElementById('effect-area'); // elem.children[elem.childElementCount - 1].remove(); } }); return ( <div> <h3>React 18 Strictモード</h3> <ul id="effect-area"></ul> </div> ); } export default App;
リスト2のuseEffectフックの引数に与えた関数で、副作用の実行処理(1)を指定します。また、その関数内でreturnする関数でクリーンアップの処理(2)を指定します。副作用では(1a)の処理でリストに1行追加しますが、副作用が複数回実行されると、その回数だけリストに行が追加されてしまいます。副作用の処理に対応するクリーンアップ処理(2a)は、ここではコメントアウトされています。
そのため、index.jsでリスト1の通りStrictモードが設定されている場合、(1a)の処理が2回実行されて、リストに2行表示されます。この時コンソールログを見ると、「副作用の実行→クリーンアップ→副作用の実行」の順番で実行されていることがわかります(図4)。
index.jsで<React.StrictMode>タグを削除すると、リスト2のコンポーネントは想定通りリストが1行だけになります。この時のコンソールログは「副作用の実行」が1回だけ出力されます(図5)。
しかし、この状態ではReactの将来バージョンで不具合を起こすかもしれません。リスト2(2a)のクリーンアップ処理を有効にすると、Strictモードでも想定通りの動作となり、将来発生しうる不具合を事前に抑止できます。
なおStrictモードは、開発環境で直接実行した場合のみ効果が発生し、本番ビルドには影響を与えません。