SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

フロントエンド開発における定番ライブラリ「React」の最新バージョン解説

フロントエンド開発の定番「React」バージョン18の新機能を解説──並行レンダーで操作感が向上!

  • このエントリーをはてなブックマークに追加

 本記事では、動的なWebページを構築するフロントエンド開発にとって定番ともいえるライブラリー「React」の最新版であるバージョン18について、新機能を紹介していきます。Webページの「並行レンダー」をベースに、画面更新の優先度指定や不要な画面更新の抑制など、Webページ利用者の操作感を向上する改善が行われています。

  • このエントリーをはてなブックマークに追加

はじめに

 Reactは、動的なWebページのインターフェースを構築するためのJavaScriptライブラリーで、Facebookとオープンソースコミュニティによって開発が続けられています。

図1 Reactの公式ページ
図1 Reactの公式ページ

 Reactは2022年3月にメジャーアップデートであるバージョン18(以下「React 18」がリリースされ、現在の最新バージョンは18.2.0です。React 18の概要は公式ブログ記事で紹介されています。

図2 React 18を紹介する公式ブログ記事
図2 React 18を紹介する公式ブログ記事

 本記事では、React 18で導入された改良や新機能について、今回と次回の2回にわたって、サンプルを交えながら紹介していきます。

対象読者

  • 新バージョンでReactを体験してみたい方
  • すでにReact開発に従事していて、新機能を知りたい方
  • Reactの最新動向を追っておきたい方

必要な環境

 本記事のサンプルコードは、以下の環境で動作を確認しています。

  • Windows 10 64bit版
  • React 18.2.0
  • Node.js v18.16.0
  • Microsoft Edge 114.0.1823.43

 サンプルコードを実行するには、サンプルのフォルダーで「npm install」コマンドを実行してライブラリーをダウンロード後、「npm run start」コマンドを実行して、「https://localhost:3000」をWebブラウザーで表示します。本記事内ではReact 18の新機能に関する本質的な部分を抽出して説明しますので、それ以外の実装は各サンプルコードを参照してください。

React 18新機能のバックグラウンドとなる並行レンダー

 最初に、React 18の新機能のバックグラウンドである「並行レンダー」を紹介します。従来、Reactにおいては、画面を更新するレンダー処理が始まったら、レンダーが完了してユーザーに画面が表示されるまで、画面の更新が中断されることはありませんでした。

 しかし、React 18の並行レンダーでは、画面の更新処理が途中で中断、再開されることや、途中までの処理が打ち切られてしまうこともあります。このように、画面の更新時に並行処理を許すことで、後述する画面更新の優先順位指定など、利用者の使い勝手を向上するさまざまな新機能が提供されるようになりました。

React 18の新機能を有効にする初期化処理の方法

 React 18を利用したサンプルを紹介する前に、ReactのプロジェクトでReact 18の機能を有効にする初期化方法を紹介します。

 従来Reactを初期化するには、ReactDOM.renderメソッドにルートコンポーネントとそれを表示するHTML要素を指定して実行していました。

[リスト1]従来のReact初期化処理(p001-batching/src/index.js)
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));

 React 18では、ReactDOM.createRootメソッドに表示先のHTML要素を指定して実行し、その戻り値にルートコンポーネントを渡してrenderメソッドを実行します。

[リスト2]React 18の機能を有効にする初期化処理(p001-batching/src/index.js)
import ReactDOM from 'react-dom/client';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

 React 18の環境でも従来の記述(リスト1)で初期化することは可能ですが、その場合、React 18の新機能は有効にならず、React 17相当の挙動になります。

複数の状態変更をまとめて画面に反映するバッチングの範囲拡大

 Reactにおいては従来より、ボタンクリックなどReactのイベントハンドラー内部で発生した複数の状態変更を、まとめて1回で画面に反映する「バッチング」が行われていました。

 React 18ではさらに、PromiseやsetTimeout、JavaScriptネイティブのイベントハンドラーでもバッチングが行われるようになり、不要な再レンダリングが減少しました。この挙動を図3のサンプルで説明します。2個のボタンのどちらを押しても、画面上の数字と、その色が変更されます。

図3 バッチングのサンプル(p001-batching)
図3 バッチングのサンプル(p001-batching)

 図3のコンポーネント(App.js)は、リスト3の通りになっています。

[リスト3]図3を表示するAppコンポーネント(p001-batching/src/App.js)
function App() {
  // state ...(1)
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);
  // 直接stateを更新する処理 ...(2)
  function onClickButton1() {
    console.log('=== 直接stateを更新 ===');
    setCount(c => c + 1);
    setFlag(f => !f);
  }
  // Promise経由でstateを更新する処理 ...(3)
  function onClickButton2() {
    console.log('=== Promise経由でstateを更新 ===');
    fetchSomething().then(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
    });
  }
  // 100ms後に成功するPromiseを取得する処理 ...(4)
  function fetchSomething() {
    return new Promise((resolve) => setTimeout(resolve, 100));
  }
(略)
}

 (1)でuseStateフックを利用して、数字countと、Boolean値flagのstateを定義します。(2)はボタンクリック時のイベントハンドラーで、setCount、setFlagメソッドで状態を変更します(countを1増加、flagのtrue/falseを反転)。一方(3)では、fetchSomethingメソッド(4)で得られるPromiseにより、ボタンクリック後100ms後に(2)と同じ状態変更を行います。

 Appコンポーネントの画面内容はリスト4の通り記述します。(1)により、画面のレンダリングが行われるたびに、console.logでログが出力されます。

[リスト4]Appコンポーネントの画面表示内容(p001-batching/src/App.js)
// 画面内容を返却
return (
  <div>
    <h3>React 18 自動バッチング</h3>
    <button onClick={onClickButton1}>直接stateを更新</button>
    <button onClick={onClickButton2}>Promise経由でstateを更新</button>
    <div>↓ボタン押下ごとに数字が増えて色が変わります</div>
    <div style={{ color: flag ? 'blue' : 'red', fontSize: '25pt' }}>{count}</div>
    {console.log('レンダリング実行')} {/* (1) */}
  </div>
);

 Reactの起動処理を従来の記述(リスト1)にして図3のサンプルを実行すると、countとflagの2つの状態変更が、Reactのイベントハンドラーでは1回のレンダリングで処理されますが、Promiseでの実行では2回行われることがわかります(図4)。

図4 従来の起動方法でのレンダリングの様子(p001-batching)
図4 従来の起動方法でのレンダリングの様子(p001-batching)

 React 18から導入された新しい起動方法(リスト2)で起動した場合、図4の通り、Reactのイベントハンドラー、Promiseのいずれにおいても、countとflagの2つの状態変更が、1回のレンダリングで実行されます(図5)。

図5 新しい起動方法でのレンダリングの様子(p001-batching)
図5 新しい起動方法でのレンダリングの様子(p001-batching)

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
優先度の低い更新を後回しにできるTransition

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
フロントエンド開発における定番ライブラリ「React」の最新バージョン解説連載記事一覧
この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/17953 2023/07/06 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング