React 18で導入されたuseDeferredValueフックは、ユーザー入力の応答性を保ちながら、描画処理の負荷を軽減するための機能です。
検索やフィルタリングのように、入力に応じて重たいUI更新が起こる場面では、useDeferredValueを使うことでUXを大きく向上させることができます。
この記事では、useDeferredValueの概要を説明し、実際のコードを通じてその効果と使いどころを紹介します。
useDeferredValueとは?
useDeferredValueは、ある値の低優先度なコピーを返すフックです。Reactは即時値とは別に、優先度が低いdeferredValueを非同期的に更新するため、入力フィールドなどの即時性は保ちつつ、リスト描画などの処理を後回しにできます。
const deferredValue = useDeferredValue(value);
・value:通常の状態値
・deferredValue:遅延して更新されるコピー
従来の実装(重たい再レンダリング)
以下は、検索フィールドに入力するたびに、全アイテムをフィルタして再描画する例です。データ数が多いと、入力がカクついたり描画が遅れたりします。
import { useState } from "react";
function SearchComponent({ items }: { items: string[] }) {
const [query, setQuery] = useState("");
const filtered = items.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="検索"
/>
<ul>
{filtered.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
useDeferredValueを使った改善
以下のようにuseDeferredValueを使えば、検索入力は即時に反映しつつ、フィルター結果の描画を遅延的に処理できます。
import { useState, useDeferredValue } from "react";
function SearchComponent({ items }: { items: string[] }) {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);
const filtered = items.filter((item) =>
item.toLowerCase().includes(deferredQuery.toLowerCase())
);
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="検索"
/>
<ul>
{filtered.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
主な改善点
・入力応答の保持:入力欄は常に即時反応。UXが向上。
・パフォーマンス最適化:フィルタ結果の描画処理を低優先で実行。メインスレッドを圧迫しない。
・導入が簡単:useDeferredValueを1行追加するだけ。既存構造のまま改善できる。
まとめ
useDeferredValueは、以下のようなユースケースで特に効果を発揮します:
・入力フィールドに連動してリストをフィルタリングするようなUI
・重たいグラフ・チャート・リストが頻繁に更新されるUI
・ 即時入力の体験を保ちつつ、後続処理をスムーズにする場面
React 18以降を使用しているアプリケーションでは、「入力は早く」「描画はゆっくり」という理想的なUXをuseDeferredValueで簡単に実現できます。