React useEffectのクリーンアップタイミング

useEffectで関数をreturnしていると、副作用のクリーンアップのタイミングでその関数が実行されます。

例えばsetIntervalをクリーンアップする時などに使用します。

このクリーンアップタイミングですが、コンポーネントがアンマウントされる時に実行されますが、次のレンダーの前にも実行されます。

https://ja.reactjs.org/docs/hooks-effect.html#example-using-hooks-1

具体的な例をみてみます。

import {useEffect, useState} from "react";

const Foo = () => {
  const [message, setMessage] = useState('');

  useEffect(() => {
    const timerId = setInterval(() => {
      console.log(message);
    }, 1000);

    return () => {
      console.log('clear');
      clearInterval(timerId);
    }
  }, [message]);

  return (
    <div>
      <h2>Foo</h2>
      <input onChange={e => setMessage(e.target.value)} />
    </div>
  );
};

export default Foo;

このコードではinputに入力された文字列を1秒ごとにコンソールに出力しています。

何かしら文字を変更すると message が変更されるので、useEffect が実行されます。

このときにコンソールログを確認すると、「clear」という文字列が出力されていることがわかります。

つまり、useEffect が実行される度にクリーンアップ処理が動いており、前の setInterval はクリアされていることを意味します。

このような動作にしている理由は以下に記載されており、バグを抑制するためのものです。

https://ja.reactjs.org/docs/hooks-effect.html#explanation-why-effects-run-on-each-update