useDebugValue

useDebugValue でカスタム Hook の状態を React DevTools に分かりやすく表示する方法を学ぶ。

useDebugValue は、カスタム Hook の情報を React DevTools の表示に追加する Hook です。利用者が多いライブラリや複雑なカスタム Hook の状態を、デバッグ時だけ分かりやすくします。

状態に名前を付ける

import { useDebugValue, useSyncExternalStore } from 'react';

function subscribe(listener: () => void) {
  window.addEventListener('online', listener);
  window.addEventListener('offline', listener);
  return () => {
    window.removeEventListener('online', listener);
    window.removeEventListener('offline', listener);
  };
}

function useOnlineStatus() {
  const isOnline = useSyncExternalStore(
    subscribe,
    () => navigator.onLine,
    () => true,
  );
  useDebugValue(isOnline ? 'Online' : 'Offline');
  return isOnline;
}

サーバー描画では navigator を読まず、オンラインと仮定した初期値を返します。hydration の最初の値も同じにして表示の不一致を避け、接続状態はクライアントで購読して更新します。ここでは useDebugValue の表示対象となるカスタム Hook を、SSR に対応した形で定義しています。

たとえばデータ取得 Hook なら loading、success、error といった状態名や、取得対象の URL の一部を示せます。返す data 全体をそのまま表示する必要はありません。利用者が「なぜこの UI が今この状態なのか」を追える最小の情報を選びます。

DevTools でこの Hook を展開すると、真偽値だけでなく Online / Offline という意味のある値を確認できます。

特に複数の Hook を組み合わせる useQuery、useMediaQuery、useAuthentication のような抽象化では、内部 state をすべて公開しなくても利用者が状態を判断できます。表示用の文字列は API 利用者に返す値ではなく、開発時の診断情報です。

必要なときだけ整形する

複雑な値を文字列へ変換するコストが高い場合は、useDebugValue(value, format) の第2引数に formatter を渡します。formatter は DevTools が値を検査するときだけ呼ばれます。

アプリ固有の小さな Hook にまで追加する必要はありません。利用者が DevTools で内部状態を確認する価値があるかを基準にします。

機密情報、トークン、個人情報を debug value に入れないでください。DevTools を開く人に見える情報になるため、接続状態・件数・処理段階のような安全な要約に留めます。プロダクションのログ出力の代替でもありません。

formatter を使う場面

useDebugValue(user, (current) => current === null ? '未ログイン' : `user:${current.id}`);

第2引数の formatter は DevTools が値を表示する時にだけ呼ばれるため、重い整形処理を通常のレンダーから外せます。ただし、formatter 内でも機密値を文字列化しないようにします。

まとめ

useDebugValue は実行時の挙動を変えない開発者体験のための Hook です。再利用されるカスタム Hook の状態を、必要な範囲で可視化します。

Sources