useDebounceカスタムフックの実装
ユーザーが入力を止めるまで状態更新を遅延させるuseDebounceフックを構築します
「useDebounceカスタムフックの実装」はCoddyKit上の無料React Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
フックのシグネチャ
useDebounce フックは、値とミリ秒単位の遅延時間を受け取り、その値をデバウンスしたものを返します。function useDebounce(value, delay) のように記述します。返される debouncedValue は実際の値より遅れて更新され、別の変更がないまま指定した遅延時間が経過した後にだけ更新されます。
debouncedValue の内部状態
フック内で、状態変数を宣言します。const [debouncedValue, setDebouncedValue] = useState(value) のように記述します。この状態には、最後に確定した値が保持されます。初期値と同じ値で始まり、デバウンスタイマーが発火した後にだけ更新されます。debouncedValue を読み取るコンポーネントは、安定した確定済みの入力値を取得できます。
setTimeout を使った useEffect
中心となる処理は useEffect に記述します。setTimeout(() => setDebouncedValue(value), delay) でタイマーを作成し、その ID を保存します。エフェクトは value または delay が変わるたびに実行されます。タイマーは最後の変更から delay ミリ秒後に発火し、デバウンスされた状態を更新します。
クリーンアップでのタイマーの消去
useEffect のクリーンアップ関数では、clearTimeout(timerId) を呼び出します。タイマーが発火する前に value が変わると、React はクリーンアップを実行して、保留中の更新をキャンセルします。その後、新しいタイマーが設定されます。これがデバウンスを機能させる重要な仕組みです。値が急速に変化すると、タイマーが繰り返しリセットされます。
エフェクトの依存配列
useEffect の依存配列には [value, delay] を含める必要があります。入力値が変わるたびにエフェクトが再実行されて新しいタイマーが設定され、delay が変わった場合にも再実行されます。これにより、呼び出し側がデバウンス間隔を動的に調整できます。古いクロージャーの問題を避けるため、両方を含める必要があります。
コンポーネントでのフックの使用
使い方は簡単です。const debouncedSearch = useDebounce(searchInput, 300) のように記述します。[debouncedSearch] を依存配列とする別の useEffect で、API 呼び出しを実行します。入力の状態(searchInput)はすぐに更新されるため入力の応答性は保たれ、API 呼び出しだけがデバウンスによって遅延します。
最初の呼び出しを即時実行する場合のエッジケース
標準的な実装では、デフォルトでトレーリングエッジでのみ実行されます。最初のトリガーでは関数を呼び出し、その後の呼び出しにはデバウンスを適用する「即時」モードでは、呼び出し済みかどうかを追跡し、タイムアウト後にリセットするための ref が必要です。これはより複雑ですが、送信ボタンなどに役立ちます。
TypeScript のジェネリック型パラメーター
型安全性を確保するため、フックをジェネリックにします。function useDebounce(value: T, delay: number): T のように記述します。これにより、TypeScript は value の型から debouncedValue の型を推論できます。ジェネリックパラメーター T は、内部状態と戻り値の型に自動的に引き継がれます。
よくあるバグ:クリーンアップの欠落
よくある間違いは、useEffect からクリーンアップ関数を返し忘れることです。クリーンアップがないと、値が変わるたびに新しいタイマーが作成されますが、古いタイマーはキャンセルされません。その結果、複数のタイマーが発火し、古い値を使って setDebouncedValue が複数回呼び出されるため、デバウンスがまったく機能しなくなります。
useRef ベースのアプローチとの比較
別の方法として、lodash を使ってデバウンス関数自体を useRef に保存することもできます。状態ベースのアプローチとは異なり、ref ベースのアプローチでは値ではなくコールバック(関数)にデバウンスを適用します。派生値が必要な場合は状態ベースのフックを使い、イベントハンドラーにデバウンスを適用する場合はコールバックのアプローチを使います。
実際の動作確認
タイムアウトのコールバック内に console log を追加し、素早く入力している間のブラウザコンソールを確認して、フックが正しく動作することを検証します。キー入力ごとではなく、「入力を止めた」タイミングごとに 1 件のログが表示されるはずです。素早く入力したときのログ数は、キー入力数より大幅に少なくなるはずです。
useDebounce の useEffect クリーンアップ
useDebounce の useEffect では、なぜ clearTimeout を呼び出すクリーンアップ関数を返す必要があるのですか?
レッスンのまとめ:useDebounce フック
useDebounce(value, delay) フックは、delay ms の間イベントが発生しなかった後にだけ更新される、デバウンスされた状態を保持します。その useEffect はタイムアウトを設定し、クリーンアップ時にそれを消去して古いタイマーをキャンセルします。API を取得するエフェクトでは、デバウンスされた値を依存配列に指定します。完全な型安全性を得るには、TypeScript のジェネリックを追加します。
よくある質問
「useDebounceカスタムフックの実装」レッスンは無料ですか?
はい。「useDebounceカスタムフックの実装」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「useDebounceカスタムフックの実装」で何を学びますか?
ユーザーが入力を止めるまで状態更新を遅延させるuseDebounceフックを構築します ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「useDebounceカスタムフックの実装」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- UIでデバウンスとスロットルが重要な理由
- useDebounceカスタムフックの実装
- useThrottleカスタムフックの実装
- 実践的な活用例:検索、スクロール、リサイズ