nomurabbitのブログ

nomurabbitのブログはITを中心にした技術ブログです。

nomurabbitのブログ

【React】useEffectの第二引数についてまとめてみた【Hook】

こんにちは!nomurabbitです。
今回はuseEffectの第二引数について
紹介したいと思います。

useEffectの概要は、
前回の記事をご覧ください。

nomurabbit.hatenablog.jp

副作用の実行条件

useEffectは引数を2つ受け取ることができます。
1つ目は副作用として実行する関数、2つ目はstateの配列です。

渡された引数が1つだけ(副作用として実行する関数)だった場合、
useEffectは全てのレンダリング後に第一引数の関数を実行します。

一方で2つ目の引数が与えられていた場合、
useEffectは2つ目の引数として与えられたstateの変更に伴う
レンダリング
後にのみ第一引数の関数を実行します。

つまり、第二引数によってuseEffectの実行条件を
コントロールすることができるのです。

以下のプログラムであれば、
第一引数の関数は count に変更があった場合にのみ実行されます。

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]);

第二引数の使い方

それはなんとなくわかったけど…。
どういう時に使えばいいの?

副作用の中で、stateを変更したい場合に使えます。
次のプログラムをご覧ください。

const Home = () => {

  const [state1, setState1] = useState(0);
  const [state2, setState2] = useState(0);

  useEffect(() => {
    setState2(state2 + 1);
  },[state1]);
  
  return (
    <ResponsiveDrawer>
      <div>
        <p>home page.</p>
        <p>state1 is {state1}</p>
        <p>state2 is {state2}</p>
        <button onClick={() => {setState1(state1 + 1);}}>
          Click me
        </button>
      </div>
    </ResponsiveDrawer>
  );
}

こちらのプログラムは

  1. state1の変更
  2. レンダリング
  3. 副作用内でstate2を変更
  4. レンダリング
  5. 終了

という処理を意図しています。

実行すると意図したとおり
このような結果になります。

f:id:nomurabbit:20211214001615g:plain

では次に、第二引数を指定せずに
実行するとどうなるでしょうか?

const Home = () => {

  const [state1, setState1] = useState(0);
  const [state2, setState2] = useState(0);

  useEffect(() => {
    setState2(state2 + 1);
  });
  
  return (
    <ResponsiveDrawer>
      <div>
        <p>home page.</p>
        <p>state1 is {state1}</p>
        <p>state2 is {state2}</p>
        <button onClick={() => {setState1(state1 + 1);}}>
          Click me
        </button>
      </div>
    </ResponsiveDrawer>
  );
}

結果はこんな感じです。

f:id:nomurabbit:20211214001707g:plain

state1を変更した場合に加え、
state2を変更した場合にも関数が実行されるため、
無限ループに陥ってしまいました。

プログラムの意図としては、下記の図に示す通り
state2の変更時に副作用を実行してほしくないわけです。

f:id:nomurabbit:20211213233110p:plain

このような場面でuseEffectの第二引数が効果を発揮します。
第二引数に適切なstateを指定することで、
副作用の実行を特定のstate変化に制限することができます。

useEffect(() => {
  setState2(state2 + 1);
},[state1]);

副作用でAPIからデータを取ってきて、
stateにセットしてレンダリングする。
なんて時にも活躍しそうですね!

以上がuseEffectの第二引数についての紹介となります。
なんとなくの概念だけでも
ご理解いただけましたでしょうか?

次回もぜひご覧ください。
では!