useEffectを使いすぎてた私がMeta社の調査結果を見て反省した話
こんにちは。とちです。
Reactで開発していて、「useEffect書きすぎかも…」と感じたことはありませんか?私はしょっちゅうありました。
そんな中、Meta社(旧Facebook)が自社のコードベースを調査したら、useEffectの約46%が実は不要だったという調査結果を知って、かなり衝撃を受けました。
この記事では、私がuseEffectを使いすぎていた理由を反省しつつ、どうやって減らしていったかを共有します。
React公式ガイドライン:useEffectは「避難ハッチ」
useEffectの本来の役割
React公式ドキュメントでは、useEffectを「Reactパラダイムからの避難ハッチ」として位置づけています。この表現は、useEffectが外部システムとの同期という限定的な用途のために設計されていることを示しています。
避難ハッチとは、通常の手段では対応できない特殊な状況でのみ使用される仕組みです。useEffectも同様に、Reactの宣言的なパラダイムでは表現できない処理に限って使用するべきです。
Meta社の調査結果から見えるuseEffectの課題
React開発元のMeta社が自社のコードベースを調査した結果、興味深い事実が明らかになりました。
この調査結果は、React開発チーム自身がuseEffectの適切な使用について継続的に改善を続けていることを示しています。同時に、useEffectの使用判断が技術的に難しい問題であることも表しています。
私がuseEffectで苦労したこと
1. メンテナンスが大変だった
実際にuseEffectをたくさん使ったコンポーネントを書いてみて、こんなことに困りました:
- 依存関係の追跡が困難
- 副作用の連鎖による予期しない動作
- デバッグに要する時間の増加
実際の開発現場では、useEffectの依存配列や実行タイミングの理解不足により、バグの原因特定に長時間を要するケースが見られます。
こんな感じでuseEffectが連鎖していくと、どこで何が起きているのか分からなくなって、デバッグにすごく時間がかかりました。
2. パフォーマンスも悪くなった
useEffectを連鎖させると、再レンダリングが何度も起きてしまいました。
私がやってしまっていたアンチパターン
1. 派生状態の計算
アンチパターン:
改善方法:
2. 高価な計算のキャッシュ
アンチパターン:
改善方法:
3. イベントハンドリング
アンチパターン:
改善方法:
4. データフェッチング
アンチパターン:
改善方法(React 18以降):
どんな時にuseEffectを使うべきか学んだこと
useEffectを使うべき場面
-
外部システムとの同期
- DOM操作(focus、scroll位置の制御)
- 外部ライブラリとの連携
- WebSocket接続の管理
-
副作用の管理
- タイマーの設定・解除
- イベントリスナーの登録・解除
- 外部APIとの通信(React 18以前)
useEffectを使わない方がいい場面
-
レンダリング時に計算できる値
- 他のstate/propsから算出できる値
- フィルタリング・ソート・集計処理
-
ユーザー操作への応答
- フォームバリデーション
- ボタンクリック時の処理
- 条件分岐による状態更新
-
コンポーネント間の状態同期
- 共通のstate管理ライブラリを使用
- 状態のリフトアップを検討
ESLintに怒られ続けた日々
最初の頃はreact-hooks/exhaustive-deps
のエラーがうっとうしくて、無効化したくなったこともありました。でも、これは「useEffectの使い方が間違ってるよ」というReactからのメッセージだったんですね。
カスタムフックによる抽象化
useEffectが必要な場合は、カスタムフックに抽出することで、より宣言的で保守しやすいコードを書けます。
まとめ
useEffectをたくさん使っていた頃の自分を振り返ると、「もっとシンプルに書けたのになぁ」と思います。
Meta社の調査結果を知ってから、意識的にuseEffectを減らすようにしました。結果として:
- コードが読みやすくなった
- デバッグが楽になった
- パフォーマンスも改善した
今では「まずuseEffectを使わないでできないか考える」という習慣が身につきました。
もしあなたも「useEffect多いかも…」と感じていたら、ぜひ一度見直してみてください。意外と簡単に減らせるかもしれませんよ。