使い方に悩んだuseEffectを、個人的にまとめてみました!
誰かの役に立てれば嬉しいです。
※公式さんはこちらuseEffect
useEffectとは?
- Reactコンポーネントに存在する副作用関数を、特定のタイミングで実行する関数である
構文
useEffect(setup, dependencies?)
setup
-
コンポーネントがDOMに追加されると、ReactはuseEffectに渡された第一引数を実行する(SPAのような動きと言われている理由・・・?)
-
再レンダリングされるたび・コンポーネントがDOMから削除されたとき、古い値を使用してクリーンアップ関数を実行する
- 次に新しい値を使用してセットアップ関数を実行
dependencies
- 指定することで、リアクティブの値が依存関係として正しくしているかどうかが検証される
- 省略するとコンポーネントが再レンダリングされるたびにエフェクトが再実行される
注意事項
-
クライアント上でのみ実行される
- サーバー レンダリング中には実行されない
-
useEffectで、関数コンポーネント内で副作用を実行することができるようになる
-
副作用のない関数、ある関数とは?
例①:JSXあるいはTSXからUIを構築する処理=DOMの書き換え操作、イベント処理etc
例②:サーバー通信(APIコール)
例③:以下のような、同じ入力で同じ出力を返却しないもの
-
// 副作用がない関数
function double(x: number) :number {
return 2 * x;
}
// 副作用がある関数
let num = 0;
// グローバル変数numを参照し、それを増加させて返す関数
function add(x: number): void {
num = num + x;
}
-
第二引数に設定したstateを第一引数で更新しない=無限ループになるため
- 必要な場合は条件分岐で制御をかけること
-
Promiseを直接指定しないこと(?)
-
useEffect
に直接async
関数を渡すと、非同期処理を待てない - 代わりに、非同期処理をuseEffectのコールバック関数内で行う必要がある
- コールバック関数:他の関数を引数として渡す関数のこと(オブジェクトなので可能)
-
実行順序
- useStateの更新関数等によって関数の値が書き換える
- 画面を再レンダリングする
- 2で変更がある場合、DOMを書き換える
- useEffectの第一引数に渡した処理を実行する
実行タイミング
-
第二引数に何も指定しない場合
レンダリング(Mounting, Updating, Unmounting)毎に実行します。
つまり、コンポーネント内で値が変わり、再レンダリングされるような場合には再レンダリング毎に実行します。
-
第二引数に空の配列を指定した場合
初回レンダリング時のみ実行されます。
-
第二引数の配列に1つ以上の値が指定されている場合
渡された値がレンダリング前後で変更がなければ処理をスキップし、再レンダリング後に変更していれば実行します。
クリーンアップについて
- クリーンアップとは:
- コンポーネントが消失されたときに実行される
-
クリーンアップを設定しないと、コンポーネントが消失しても、バックグラウンドで動き続けてしまう可能性がある
- 戻り値として設定する
useEffect(() => {
return () => {
// クリーンアップ関数実行
};
}, [time]);
- 記載例
- intervalを設定して、クリーンアップのところでclearする
useEffect(() => {
let interval = null;
interval = window.setInterval(() => {
console.log("interval called");
setTime((prev) => prev + 1);
}, 1000);
return () => {
window.clearInterval(interval);
};
}, []);