react-component-performance について
遅いコンポーネントの原因特定や不要な再レンダリングの削減を支援する、React 開発者向けのパフォーマンススキルです。最適化パターンを提示し、React DevTools Profiler で基準記録と比較して検証します。
主な機能
- 01再レンダリング要因とホットスポットの特定
- 02頻繁に変わる状態の分離
- 03プロパティとコールバックの安定化
- 04計算処理とリスト描画の削減
- 05最適化前後のプロファイル比較
活用シーン
- 01遅い React コンポーネントの診断
- 02リスト内の再レンダリング削減
- 03プロファイリングによる最適化の検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ shipshitdev/ skills --skill react-component-performanceインストール後、Claude Code で/react-component-performanceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
plugin.jsonREADME.mdagents/openai.yamlreferences/examples.md詳細
React コンポーネントのパフォーマンス
レンダリングのボトルネックを特定し、負荷の高い更新を切り分け、UI の動作を変えずに的を絞った最適化を適用します。
使用するタイミング
- ユーザーから、React コンポーネントのプロファイリングやパフォーマンス改善を求められた場合。
- React UI で再レンダリング、リストの遅延、または負荷の高いレンダリング処理を減らす必要がある場合。
API のレイテンシ、データベースクエリ、キャッシュ、バックグラウンドジョブ、インフラの
チューニングには、代わりに performance-expert を使用してください。
ワークフロー
- 遅延を再現するか、内容を説明します。
- 再レンダリングを引き起こす要因(state の更新、props の頻繁な変更、effects)を特定します。
- 頻繁に変化する state を負荷の高いサブツリーから切り離します。
- props とハンドラーを安定させ、効果が見込める箇所をメモ化します。
- 負荷の高い処理(計算、DOM サイズ、リストの長さ)を減らします。
- 検証:React DevTools Profiler を開き、操作を記録し、Flamegraph で約 16 ms を超えてレンダリングされるコンポーネントを確認します。最適化前に記録したベースラインと比較します。
チェックリスト
- 計測:React DevTools Profiler を使用するか、レンダリングをログに記録して、ベースラインを取得します。
- 頻繁な更新を特定:タイマー、スクロール、入力、アニメーションで更新される state を特定します。
- 分割:更新頻度の高い state を子コンポーネントに移し、負荷の高いリストを静的に保ちます。
- メモ化:props が安定している場合に限り、リーフ行を
memoでラップします。 - props を安定化:ハンドラーや派生値に
useCallback/useMemoを使用します。 - レンダリング中の派生処理を避ける:事前に計算するか、メモ化したヘルパー内で計算します。
- リストのサイズを制御:長いリストにはウィンドウ化/仮想化を使用し、非表示の項目はレンダリングしないようにします。
- キー:キーが安定していることを確認します。順序が変わる可能性がある場合はインデックスを避けます。
- Effects:依存配列を確認し、レンダリングのたびに再実行される effects を避けます。
- スタイル/レイアウト:負荷の高いレイアウトの頻繁な再計算や、大きな Markdown/diff のレンダリングに注意します。
最適化パターン
頻繁に更新される state を切り離す
タイマーやアニメーションのカウンターを子コンポーネントに移し、親のリストが更新のたびに再レンダリングされないようにします。
// ❌ Before – entire parent (and list) re-renders every second
function Dashboard({ items }: { items: Item[] }) {
const [tick, setTick] = useState(0);
useEffect(() => {
const id = setInterval(() => setTick(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return (
<>
<Clock tick={tick} />
<ExpensiveList items={items} /> {/* re-renders every second */}
</>
);
}
// ✅ After – only <Clock> re-renders; list is untouched
function Clock() {
const [tick, setTick] = useState(0);
useEffect(() => {
const id = setInterval(() => setTick(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return <span>{tick}s</span>;
}
function Dashboard({ items }: { items: Item[] }) {
return (
<>
<Clock />
<ExpensiveList items={items} />
</>
);
}
useCallback と memo でコールバックを安定化する
// ❌ Before – new handler reference on every render busts Row memo
function List({ items }: { items: Item[] }) {
const handleClick = (id: string) => console.log(id); // new ref each render
return items.map(item => <Row key={item.id} item={item} onClick={handleClick} />);
}
// ✅ After – stable handler; Row only re-renders when its own item changes
const Row = memo(({ item, onClick }: RowProps) => (
<li onClick={() => onClick(item.id)}>{item.name}</li>
));
function List({ items }: { items: Item[] }) {
const handleClick = useCallback((id: string) => console.log(id), []);
return items.map(item => <Row key={item.id} item={item} onClick={handleClick} />);
}
派生データはレンダリングの外で処理する
// ❌ Before – recomputes on every render
function Summary({ orders }: { orders: Order[] }) {
const total = orders.reduce((sum, o) => sum + o.amount, 0); // runs every render
return <p>Total: {total}</p>;
}
// ✅ After – recomputes only when orders changes
function Summary({ orders }: { orders: Order[] }) {
const total = useMemo(() => orders.reduce((sum, o) => sum + o.amount, 0), [orders]);
return <p>Total: {total}</p>;
}
その他のパターン
- 行を分割する:リストの行を、props を絞ったメモ化コンポーネントとして切り出します。
- 負荷の高いレンダリングを遅らせる:負荷の高いコンテンツは、展開されるまで遅延レンダリングするか折りたたんでおきます。
プロファイリングの検証手順
- React DevTools → Profiler タブを開きます。
- Record をクリックし、遅い操作を行ってから Stop をクリックします。
- Flamegraph ビューに切り替えます。コンポーネント名と約 16 ms を超える時間が表示されたバーが、最適化候補です。
- Ranked chart を使って自己レンダリング時間で並べ替え、上位の問題箇所を対象にします。
- 一度に 1 つの最適化を適用し、再度記録して、レンダリング回数と所要時間をベースラインと比較します。
参考例
ユーザーが具体的なリファクタリング例を求めている場合は、references/examples.md を読み込みます。
コメント
Markdown 対応