Reactで画面を更新したときにだけ処理したいとき、どうしてますか?
私は、こうしてました。
const defaultFunc = ()=>{
処理
}
defaultFunc();
しかしですね
これだと無限ループが起こりかねないとのこと。
皆さんご経験があるかと思いますが、無限ループすると、Reactからレンダリングしすぎ!!!と怒られます。
どうして無限ループが起こるのか
前提として、ステートが更新されると、再描画が起こります。
再描画されたときにもReactは上から処理を読み込んでいくので、
画面更新時の処理defaultFunc
にステートを更新するような処理setState
が含まれている場合、下記のような流れになります。
- 最初に画面を表示したとき
defaultFunc
- ステートを更新する処理
setState
- ステートを更新したので再描画が起こる
- 再描画されたので、
defaultFunc
が走る - ステートが更新される
setState
- 以下ループ
ではどうする
useEffectを使う。
useEffectとは
ステートを監視して、変更があった場合に第一引数で定義した処理を行う。
監視する対象のステートは第二引数で指定可能。
そして、ステートに変更があったときだけでなく、初回レンダリング時にも動くのです。
(初回レンダリング時に動かないようにしたい記事はよく見かけますね・・)
React公式にもこのようにあります。
初回のレンダー時および毎回の更新時に呼び出されます。
解決策
useEffectの第二引数に空配列をいれる。
useEffect(() => {
defaultFunc();
}, [])
React公式では下記のように記載あります。
(日本語としてわかりにくいですね・・・公式ドキュメント読みたくなくなる理由がここにある。)
もしも副作用とそのクリーンアップを 1 度だけ(マウント時とアンマウント時にのみ)実行したいという場合、空の配列 ([]) を第 2 引数として渡すことができます。こうすることで、あなたの副作用は props や state の値のいずれにも依存していないため再実行する必要が一切ない、ということを React に伝えることができます。