📝
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;
setTime(prev => prev + 1)
を実行。
(1) 1000ms(=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