useEffectにおける「沈黙のバグ」。
それは、依存配列に値を入れ忘れているがゆえに、処理が再実行されず、バグにすら気づかれない状態を指します。

これは一見「安定して動いている」ように見えるため、
レビュー時に見落とされやすい典型的な“静かな副作用”です。

コードが「壊れていることに気づけない」構造

NG例:依存配列の省略
useEffect(() => {
  if (searchKeyword.length > 2) {
    fetchData(searchKeyword);
  }
}, []);
@Reviewer
`searchKeyword` が依存配列に含まれておらず、変化時に `useEffect` が再実行されません。初期状態のみでしか機能しない副作用になっています。

このようなコードは初回だけ動作し、その後は沈黙します。
テストコードでは検出しにくく、レビューでしか見抜けないタイプの構造不備です。

なぜ発生するのか:useEffectの設計意図

useEffect(fn, deps)deps(依存配列)は、副作用の再実行条件を明示する場所です。
しかし実際の実装では以下のような傾向があります。

  • 実装者が deps を空配列にして「初回だけ」に意図を絞るケース
  • 実行時の変数を含めるべきか迷う構造になっており、曖昧なまま残るケース
  • eslint-plugin-react-hooks をOFFにしているプロジェクトで見逃される

こうしたケースでは、期待していた再実行が起きずにUIが“固まる”といった形でユーザーに影響します。

レビュー観点:何を含めるべきか

依存配列には「副作用関数の中で使用されるすべての参照値」を含めるのが原則です。
ただし、これを形式的に守るだけでは不十分です。

改善例:明示的に依存を含める
useEffect(() => {
  if (searchKeyword.length > 2) {
    fetchData(searchKeyword);
  }
}, [searchKeyword]);

レビューでは、「この副作用が何に依存しているか」を言語化し、
配列との対応関係が論理的に一致しているかをチェックする必要があります。

パターン:関数やContextの参照漏れ

useContextの依存漏れ
const user = useContext(UserContext);

useEffect(() => {
  if (user.isAdmin) {
    setAdminMode(true);
  }
}, []);
@Reviewer
`user` は `UserContext` に依存しており、実行時には参照が変化し得るため、依存配列に含めるべきです。

チェックリスト:依存配列のレビュー観点

図解:依存漏れによる非再実行の構造

UML Diagram

まとめ

副作用が「一度だけ動く」設計は、その意図が明確であれば問題になりません。
しかし意図せずに「その後動かない」設計になっている場合、それは実装上の誤りです。

レビューアーは、useEffectの“沈黙”に注目する必要があります。
再実行されていない副作用が、設計通りのものかどうか。依存配列に値が足りているか。

副作用が静かに壊れていないか、レビューで見抜くことが品質を守る鍵になります。