Reactのパフォーマンス最適化フックuseTransition

パフォーマンス最適化フック useTransitionは、 UIをブロックせずにステートを更新することを可能にします。

このフックを使用することで、特定のステートの更新を低い優先度に設定できます。これにより、他のステートの更新は高い優先度を持ち、遅延なく実行されることができます。

例としては、ユーザーが検索フィールドに文字を入力する際の商品ドロップダウンリストのフィルタリングが挙げられます。もちろん、リスト自体は多少の遅延を持って表示されるかもしれませんが、検索フィールドへの文字入力が遅延することは避けたいでしょう。

このようなケースでフックuseTransitionがどのように役立つかを見てみましょう。 メインコンポーネントのコードの一部があると仮定します。分析してみましょう:

App.jsximport { useTransition } from 'react';
import { useState } from 'react';

function App() {
  const [isPending, startTransition] = useTransition();
  const [filterTerm, setFilterTerm] = useState('');
  
  const filteredProducts = filterProducts(filterTerm);
  
  function updateFilterHandler(event) {
    startTransition(() => {
      setFilterTerm(event.target.value);
    });
  }
 
  return (
    <div>
      <input type="text" onChange={updateFilterHandler} />
      <ProductList products={filteredProducts} />
    </div>
  );
}

ここでは、useTransitionのための2つの変数が見えます。変数isPendingはブーリアン値を持ち、更新プロセスが完了したかどうかを示します。一方、startTransitionは更新の優先度を下げることを可能にする関数です:

App.jsxconst [isPending, startTransition] = useTransition();

また、入力フィールドに入力される式を保持するステートfilterTermと、それを設定するための関数setFilterTermがあります:

App.jsxconst [filterTerm, setFilterTerm] = useState('');

入力フィールドに文字が入力されるたびに、関数updateFilterHandlerが呼び出され、その中でfilterTermの更新が行われます。 ここでまさに、私たちはフックuseTransitionを適用し、設定関数setFilterTermを以下のようにstartTransitionでラップします:

App.jsxfunction updateFilterHandler(event) {
  startTransition(() => {
    setFilterTerm(event.target.value);
  });
}

これにより、ステートfilterTermの更新に低い優先度を設定し、入力フィールドの応答性を維持することができます。

変数isPendingを使用して、リストの更新がまだ進行中であることをユーザーに表示することができます。 リストが更新されている間、この情報を入力フィールドの下に表示してみましょう:

App.jsxreturn (
  <div>
    <input type="text" onChange={updateFilterHandler} />
    {isPending && <p>更新中 ...</p>}
    <ProductList products={filteredProducts} />
  </div>
);