React DevTools Profiler:再レンダリングを特定してパフォーマンス改善

スポンサーリンク

React DevTools Profiler:再レンダリングを特定してパフォーマンス改善

Profilerタブとは

React DevToolsの「Profiler」タブはReactコンポーネントのレンダリングを録画・計測するツールです。どのコンポーネントが何回・何ms かかって再レンダリングされたかを可視化でき、パフォーマンス問題の原因を特定できます。


開き方

  1. ブラウザの開発者ツールを開く(F12
  2. ⚛ Profiler」タブを選択

録画の基本操作

録画開始 → 操作 → 録画停止

  1. 左上の ● 録画ボタンをクリック(赤くなる)
  2. アプリ上で計測したい操作を行う(ボタンクリック・入力・ページ遷移など)
  3. 録画ボタンを再度クリックして停止

録画が終わると結果が表示されます。


フレームグラフの見方

録画後に「Flamegraph」タブが表示されます。

Commit #1  Commit #2  Commit #3
  5.2ms      1.1ms      8.7ms

上部にコミット(Reactが実際にDOMを更新したタイミング)のリストが表示されます。数字はそのコミットの処理時間です。

フレームグラフの色

意味
グレー 今回のコミットで再レンダリングされなかった
青〜黄 再レンダリングされた(明るいほど時間がかかっている)
赤・オレンジ 時間がかかっている(要注意)

グレーのコンポーネントはスキップされており、パフォーマンスに影響しません。


再レンダリングの原因を確認する

フレームグラフでコンポーネントをクリックすると右ペインに詳細が表示されます。

UserCard
レンダリング時間: 3.2ms
レンダリングされた理由: props が変わった
  name: "田中" → "田中太郎"

レンダリングされた理由 の表示:

表示 意味
props が変わった 親から渡されたpropsが変化した
state が変わった 自身のstateが変化した
context が変わった useContextの値が変化した
フックが変わった useStateやuseReducerの値が変化した
親がレンダリングされたため propsが変わっていないのに親の再レンダリングに巻き込まれた ← 改善候補

「親がレンダリングされたため」が表示されたコンポーネントは React.memo で最適化できる可能性があります。


Ranked チャートの見方

「Ranked」タブに切り替えると、レンダリング時間が長い順にコンポーネントが並びます。

HeavyList    ████████████ 12.3ms
UserCard     ████ 3.2ms
Header       ██ 1.1ms

どのコンポーネントがボトルネックになっているかを素早く把握できます。


最適化の前後を比較する

React.memo で不要な再レンダリングを防ぐ

// 最適化前:親が再レンダリングするたびにUserCardも再レンダリング
function UserCard({ name }: { name: string }) {
  return <div>{name}</div>
}

// 最適化後:propsが変わらなければスキップ
const UserCard = React.memo(({ name }: { name: string }) => {
  return <div>{name}</div>
})

Profilerで録画 → React.memo を適用 → 再度録画して比較することで効果を確認できます。

useCallback でコールバックの再生成を防ぐ

// 毎回新しい関数オブジェクトが生成されるため、React.memoが効かない
function Parent() {
  const handleClick = () => { /* ... */ }
  return <Child onClick={handleClick} />
}

// useCallbackで関数を安定させる
function Parent() {
  const handleClick = useCallback(() => { /* ... */ }, [])
  return <Child onClick={handleClick} />
}

useMemo で重い計算をスキップする

// レンダリングのたびに重い計算が実行される
function Component({ data }: { data: number[] }) {
  const result = heavyCalculation(data) // 毎回実行

  // useMemoでdataが変わったときだけ計算する
  const result = useMemo(() => heavyCalculation(data), [data])
  return <div>{result}</div>
}

Profilerの設定

歯車アイコン → 「Profiler」タブで以下を設定できます。

設定 説明
Record why each component rendered なぜ再レンダリングされたか記録する(推奨)
Hide commits below X ms 短時間のコミットを非表示にして見やすくする

「Record why each component rendered」は有効にしておくと、レンダリング理由が右ペインに表示されてデバッグが楽になります。


よくある改善パターン

症状 原因 対策
子コンポーネントが毎回再レンダリングされる propsが変わっていないのに親が再レンダリング React.memo を適用
React.memo を付けても再レンダリングされる 関数・オブジェクトのpropsが毎回新規生成 useCallback / useMemo で安定させる
特定のコンポーネントだけ遅い 重い計算がレンダリングごとに実行される useMemo で計算をキャッシュ
リスト全体が遅い リストアイテムが毎回全件再レンダリング React.memo + key の見直し

まとめ

録画開始 → 操作 → 録画停止
  ↓
Flamegraphで時間がかかっているコンポーネントを確認
  ↓
「親がレンダリングされたため」の箇所を React.memo で対応
  ↓
再度録画して改善を確認
ツール 用途
Flamegraph コミットごとのレンダリング構造を視覚化
Ranked レンダリング時間が長い順に確認
レンダリング理由 なぜ再レンダリングされたかを特定
React.memo propsが変わらなければスキップ
useCallback 関数を安定させてmemoを有効にする
useMemo 重い計算をキャッシュ

DevToolsの基本(Components タブ)は「React DevTools 入門:Components タブでpropsとstateを確認する」を参照してください。

Reactのプロジェクト作成から始める場合は「React + Vite でプロジェクト作成」を参照してください。