React の useEffect の依存配列と後片付け (クリーンアップ) を説明してください

useEffect は描画のあとに外の世界 (タイマー、購読、通信など) と同期するためのフックで、依存配列の値が変わったときだけやり直し、やり直す前と消える前に後片付けを呼ぶ、と答える問い。配列を省いたとき、空のとき、値を入れたときの違いまで話します。

答えてみる

面接官に「React の useEffect の依存配列と後片付け (クリーンアップ) を説明してください」と聞かれたつもりで、答えを見る前に自分の言葉で答えます。

声に出して答えた人は「書かずに答えを見る」で開けます。

解説を読む

聞かれ方から関連するコースまで、この問いの解説を全部ここに置いています。

こう聞かれます

  • 「useEffect の依存配列は何のためにありますか」
  • 「依存配列を空にしたとき、省いたとき、値を入れたときの違いは」
  • 「useEffect で return する関数は何ですか。いつ呼ばれますか」

面接官が見ている点

  • useEffect は「描画のあとに、React の外の物と同期する」ための物だ、と言えるか
  • 依存配列の 3 つの書き方の違いを、いつ動くかで言えるか
  • 後片付けが、次の実行の前とアンマウントのときに呼ばれると分かっているか
  • 依存配列から値を抜いて警告を黙らせると、古い値を使う不具合になると知っているか

短い答え

  • useEffect は、描画のあと (多くは画面に反映されたあと) に、タイマー、イベントの購読、外部への接続など、React の外の物と同期する処理を書く場所です。
  • 依存配列に書いた値が前回と変わったときだけ、処理をやり直します。空の配列なら最初に表示されたときだけ、配列を省くと毎回の描画のあとに動きます。
  • 処理から返した関数が後片付けで、次にやり直す前と、部品が画面から消えるときに呼ばれます。タイマーの解除や購読の取り消しをここに書きます。

この問いを含む分野をレッスンで練習する

レッスンを開く

少し詳しい答え

基本の形

TypeScript (JSX)

function Clock() {
  const [now, setNow] = useState(new Date());

  useEffect(() => {
    // 同期を始める
    const id = setInterval(() => setNow(new Date()), 1000);
    // 後片付け
    return () => clearInterval(id);
  }, []); // 最初の表示のときだけ始める

  return <p>{now.toLocaleTimeString()}</p>;
}

後片付けが無いと、画面から消えたあともタイマーが残り、1 秒ごとに処理を続けます。画面を行き来するたびにタイマーが増え、無駄な処理とメモリが積み上がります。

依存配列の 3 つの書き方

書き方動くとき
配列を省く毎回の描画のあと
[]最初に画面に出たときだけ
[roomId]最初と、roomId が前回と変わったとき

値が変わったかどうかは Object.is で比べます。描画のたびに新しく作るオブジェクトや関数を入れると、毎回「変わった」と判定されます。

値が変わったときの流れ

チャットの部屋に接続する例で、roomId が "a" から "b" に変わると、次の順で動きます。

  1. 新しい roomId で描き直す
  2. 前の処理の後片付けを呼ぶ ("a" から切断)
  3. 新しい値で処理を動かす ("b" に接続)

TypeScript (JSX)

useEffect(() => {
  const connection = createConnection(roomId);
  connection.connect();
  return () => connection.disconnect();
}, [roomId]);

「始める」と「止める」を対で書いておけば、何度やり直しても正しく動きます。

依存配列は「自分で選ぶ物」ではない

処理の中で使っている props と state は、全部依存配列に入れます。linter (eslint-plugin-react-hooks) が足りない値を教えてくれます。値を抜いて警告を黙らせると、処理が古い値を使い続ける不具合になります。動く回数を減らしたいときは、配列から抜くのではなく、処理の中で使う値を減らす (オブジェクトを処理の中で作る、更新関数を使うなど) 方向で直します。

よくある間違い

  • 後片付けを書かないタイマーや購読が残って処理を続け、画面を行き来するたびに増えていきます
  • linter の警告を消すために依存配列から値を抜く古い値を使い続けます。使う値を減らす方向で直します
  • 依存配列に入れた state を、同じ Effect の中で set する変わる、動く、また変わる、と描き直しが止まらなくなります。計算できる値なら描画の中で計算し、Effect では set しません
  • ボタンを押したときの処理を useEffect に書く押したことがきっかけなら、イベントの処理の中に書きます

深掘りの問い

  • 「開発中だけ useEffect が 2 回動くのはなぜ」 Strict Mode が、後片付けの書き忘れを見つけるために、接続、切断、接続を 1 回多く試すから、と答えます
  • 「useEffect でデータを取るときの注意は」応答が順番どおりに来るとは限らないので、後片付けで古い応答を捨てる、と答えます
  • 「useEffect が要らない場面は」 props や state から計算できる値、ボタンを押したときの処理は、useEffect を使わずに書ける、と答えます

出典

確認日 2026年10月28日書き手 小尾 知希 (講師)

技術面接問題の一覧へ戻る