useCallback利用時の注意事項
useCallback
は関数の再生成を防ぐことでパフォーマンスを最適化できる便利なHooksですが、使い方を間違えると逆にバグやパフォーマンス悪化を招くことがあります。このページでは、useCallbackを安全に使うための注意点を整理します。
1️⃣ 依存配列の指定ミスに注意
const handleClick = useCallback(() => {
doSomething(data) // ← dataに依存している
}, [])
この例では data
に依存しているにもかかわらず、依存配列に含めていないため、古いdataを参照したままの関数がキャッシュされてしまう可能性があります。
✅ 正しくは:
const handleClick = useCallback(() => {
doSomething(data)
}, [data])
2️⃣ 無意味な useCallback の使用は逆効果
const handleClick = useCallback(() => {
console.log('clicked')
}, [])
- このようなコストの低い関数に useCallback を使っても効果はほぼない。
- Reactは関数再生成自体にコストを感じにくいため、むしろメモ化のコストの方が重くなることも。
✅ 結論:再レンダリングのトリガー回避が目的のときだけ使うべき
3️⃣ useCallback + React.memo の組み合わせに注意
React.memo を使って子コンポーネントの再レンダリングを防ぐ場合、親から渡す関数が毎回再生成されていると memo の効果がなくなります。
// NG例:毎回新しい関数
<Child onClick={() => console.log('click')} />
✅ useCallbackを使って関数の参照を安定させる:
const handleClick = useCallback(() => {
console.log('click')
}, [])
<Child onClick={handleClick} />
4️⃣ 過剰な useCallback はコードの可読性を損なう
- 無闇にuseCallbackを使うと、逆に「何に依存しているか」を毎回考えねばならず、コードが読みにくくなる。
- 「後から依存が増えるリスク」もあるため、明確なメリットがあるときのみに限定するのが◎。
✅ まとめ
注意点 | 解説 |
---|---|
依存配列を正しく設定する | キャッシュ対象の関数が依存する変数はすべて列挙 |
無意味なuseCallbackは避ける | 常にパフォーマンス改善につながるとは限らない |
props最適化の目的が明確なときだけ使う | React.memoとセットで使う場合に効果が出る |
使いすぎると可読性・保守性が下がる | 記述量やバグのリスクが増える可能性がある |
🔗 関連リンク