React useEffectの働き方
前回の記事で useStateはどうやって働いているのか、わかりやすく説明しました。今回はuseEffectを説明します。
まだ読んでいない方は、↑の記事をご覧になってください。
下準備
個人的には、hooksはCache見たいなもの。key-value的なcacheじゃなくて、実行順序に基づいてのcache システム。
では、useEffect
はどう動いているのか、まずuseEffectのtypeを見ましょう。
function useEffect(effect: EffectCallback, deps?: readonly any[]): void
要するに、depsが変わったら、実行される。
show me the code
前回のuseStateのコードを見よう。
const React = {
data: [],
currentIndex: 0,
useState(initValue) {
const index = this.currentIndex;
// dataないなら、引数の初期値を挿入
if (this.data.length <= index) {
this.data.push(initValue);
}
this.currentIndex = index + 1;
//値とsetterを返す
return [
this.data[index],
newValue => {
this.data.splice(index, 1, newValue);
}
];
},
// indexをreset
resetIndex() {
this.currentIndex = 0;
}
};
そちらに各hookにはdataあり、そのdataにdepsを保存すれば、useEffectが作れます。コードは大体こんな感じ
useEffect(callback, deps) {
const index = this.currentIndex;
// depsが変わったら、callbackを実行する
const prevDep = this.data[index];
if (!prevDep || deps.some((val, index) => val !== prevDep[index])) {
callback();
}
this.data[index] = deps;
this.currentIndex = index + 1;
}
コードがシンプルで、テストしてみましょう. CounterにuseEffect
を追加する。
const Counter = () => {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log("useEffect is called");
}, [count]);
return {
// click をmockする
click() {
setCount(count + 1);
},
render() {
return count;
}
};
};
これでrenderをシミュレーションする
console.log("1st");
let counter1 = Counter();
counter1.render();
console.log("2st");
React.resetIndex();
counter1 = Counter();
console.log("3st");
React.resetIndex();
counter1.click();
counter1 = Counter();
1回目ではcallback実行されて、2回目はcountが変わらなくて、callbackが実行されない。3回目ではcountが変わったので、callbackはもう一回実行される。
以上は予想だけだが、consoleを見ると、確かにこうなっている。
これでuseEffectも理解できました、次回はuseContextをみましょう。お楽しみに
以上では各投稿者の観点であり、zanp.lifeに責任負い兼ねます。