今回は、分かりそうで分からないuseEffectの第二引数について解説したいと思います。個人的にuseEffectそのものの理解が難しいとは思いますが、今回はuseEffectの第二引数のみに着目して解説しています。React学習の参考になれば幸いです。
該当コード
今回の該当コードは以下のようなものになります。
useEffect(() => {
// 何かしらの処理を行う関数
}, [])
useEffect(() => {
// 何かしらの処理を行う関数
}, [data])
第二引数に空配列[]、もしくは値の配列[data]が渡されていますね。
useEffectの定義上必要なだけでは?と思う方もいるかもしれませんが、この第二引数には大きな意味があります。
次の項目で具体的に見ていきましょう。
【結論】useEffectの第二引数とは
useEffectの第二引数には、第一引数に渡された関数の実行タイミングをコントロールする役割があります。第二引数を空にした場合(空配列ではないので注意)は、render毎に第一引数の処理が走ることになります。
以下のコードはrender毎に毎回実行される。
useEffect(() => {
// 何かしらの処理を行う関数
})
第二引数を空にするという行為は普通はしません。state/propsのうちいずれかが更新される度にuseEffectのbodyが走ってしまうため、やりすぎになってしまう事が多いためです。
デフォルトの動作では、副作用関数はレンダーの完了時に毎回実行されます。これにより、コンポーネントの依存配列のうちのひとつが変化した場合に毎回副作用が再作成されます。
しかし、上述のデータ購読の例でもそうですが、これは幾つかのケースではやりすぎです。新しい購読を設定する必要があるのは毎回の更新ごとではなく、source プロパティが変化した場合のみです。
参考:フックAPIリファレンス
では第二引数に空配列[]が渡された場合、第一引数の関数はどのタイミングで実行されるのでしょうか。
それは初回のレンダリング時にのみ実行されます。
また、state/propsのうちいずれかが更新される度にuseEffectのbodyが走ってしまうことを空配列[]を渡す事で回避できます。
空の配列
[]
を渡すと、この副作用がコンポーネント内のどの値にも依存していないということを React に伝えることになります。つまり副作用はマウント時に実行されアンマウント時にクリーンアップされますが、更新時には実行されないようになります。~~~~~
もしも副作用とそのクリーンアップを 1 度だけ(マウント時とアンマウント時にのみ)実行したいという場合、空の配列 (
[]
) を第 2 引数として渡すことができます。こうすることで、あなたの副作用は props や state の値のいずれにも依存していないため再実行する必要が一切ない、ということを React に伝えることができます。これは特別なケースとして処理されているわけではなく、入力配列を普通に処理すればそうなるというだけの話です。
参考:フックAPIリファレンス
一方で値の配列[data]が渡された場合はどうでしょうか。
第二引数に値の配列[data]が渡された場合は、初回のレンダリング時もしくはdataの値が変更された時にのみ第一引数の関数が実行されます。
リファレンスの該当コードでは以下の箇所です。
ここではprops.sourceの値が変更された場合にのみ、第一引数の関数が実行されるようになっています。
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
参考:フックAPIリファレンス
まとめ
- useEffectの第二引数には、第一引数に渡された関数の実行タイミングをコントロールする役割がある
- 第二引数を空にした場合は、render毎に第一引数の処理が走る
- 第二引数を空にすることは避けた方が良い
- 第二引数に空配列[]が渡された場合は、初回のレンダリング時にのみ実行される
- 第二引数に値の配列[data]が渡された場合は、初回のレンダリング時もしくはdataの値が変更された時に実行される
参考
今回は分かりそうで分からないuseEffectの第二引数について解説しました。初見だと理解が難しいとは思いますが、第二引数には何かしらの値を記述するということだけでも頭に入れておいていただけたらと思います。