📝
Pt1. UseEffectの基本的な使い方
秒数をカウントする関数コンポーネントを作成
import { useState } from 'react';
const Example = () => {
const [time, setTime] = useState(0);
window.setInterval(()=>{
setTime(prev => prev + 1)
}, 1000); ---> (1)
return (
<>
<h3>
<time>{time}</time>
<span>秒経過</span>
</h3>
</>
);
};
export default Example;
(1) 1000ms(=1秒)ごとにsetTime(prev => prev + 1)を実行。
しかし、stateの値を更新すると関数コンポーネントの再レンダリングが実行されるので、画面に表示される秒数はおかしな事になる。
秒数と再レンダリング実行時をコンソールで表示

renderと表記されているタイミングで再レンダリングが行われている。
useEffectを利用する
setInterval関数をuseEffectで囲む。
useEffect(()=>{
console.log("useEffect!");
setInterval(()=>{
setTime(prev => {
console.log(prev);
return prev + 1
})
}, 1000);
}
,[]) ---> (2)
(2) 第2引数に空の配列をセットする。
[]の配列をセットすることで最初のレンダリング時のみ、useEffectに登録した関数処理が実行される。
[]を忘れると、(1)の時と同じようにstateが更新されるたびに再レンダリングが実行されてしまう。
最初のレンダリング時のみ、useEffectに登録した関数処理が実行されている。

つまり実行されるsetInterval関数は1回のみ。
今まで変な挙動を起こしていたのはsetInterval関数が何個も登録されていたから。
useEffectの第二引数 => 依存配列
- 依存配列に time を格納してみる
import { useState, useEffect } from 'react';
const Example = () => {
const [time, setTime] = useState(0);
console.log("render");
useEffect(()=>{
console.log("useEffect!");
setInterval(()=>{
setTime(prev => {
console.log(prev);
return prev + 1
})
}, 1000);
},[])
useEffect(()=>{
console.log("useEffect has time state!");
},[time]) ---> (3)
return (
<>
<h3>
<time>{time}</time>
<span>秒経過</span>
</h3>
</>
);
};
export default Example;
(3) 第2引数にstateを持つ配列をセットする。

最初のレンダリング時と、秒数(=time)がカウントされていくたびに依存配列にtimeを持つuseEffectが実行されている。
※useEffectの中で依存配列に格納されている変数をセットしてはいけない!
useEffect(()=>{
console.log("useEffect has time state!");
setTime(prev => prev + 1);
},
[time])
依存配列に格納された変数が更新されるたびにuseEffectが呼び出されてしまうので無限ループが発生してしまう。
Discussion