useEffect を使ってコンポーネントを外の世界と同期させ、依存配列とクリーンアップを使いこなします。
このレッスンを Kodokon で開くReact コンポーネントは props と state から JSX を計算します。そのスコープの外にあるもの、つまりドキュメントのタイトルを変える、タイマーを開始する、ブラウザのイベントを購読するといったものは副作用です。useEffect はそのコードをレンダリングの後に、表示をブロックせずに実行し、特定の値が変化したときに再同期します。
import { useEffect } from "react";
function CartTitle({ count }) {
useEffect(() => {
document.title = `Cart (${count})`;
}, [count]);
return <p>Items: {count}</p>;
}依存配列は副作用がどのくらいの頻度で実行されるかを制御します。[count]: count が変化したレンダリングのたびに副作用が再実行されます。[]: 副作用は最初のレンダリングの後に一度だけ実行されます。配列なし: 毎回のレンダリングの後に副作用が再実行されますが、これはめったに望ましくありません。黄金律: 副作用の中で使うすべてのコンポーネントの値は配列に登場させなければなりません。
import { useEffect, useState } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setSeconds((s) => s + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <p>Elapsed: {seconds} s</p>;
}副作用が返す関数がクリーンアップ関数です。React はそれを副作用が新たに実行される前に毎回呼び出し、コンポーネントがアンマウントされるときに最後にもう一度呼び出します。これがリークを防ぐものです。取り残されたタイマー、積み重なったリスナー、決してキャンセルされない購読などです。何かを「開く」副作用はすべて、それを再び閉じなければなりません。
useEffect(() => {
function onResize() {
setWidth(window.innerWidth);
}
window.addEventListener("resize", onResize);
return () => {
window.removeEventListener("resize", onResize);
};
}, []);useEffect(fn, []) の場合、関数 fn はいつ実行されますか?userId を読み取るのに、その依存配列が [] です。何が問題ですか?