useEffectに関する知識
useEffectに関する知識
useEffect
は、Reactで副作用(データ取得、DOM操作、サブスクリプションなど)を処理するための重要なフックです。
ポイント
- 副作用処理(データ取得やDOM操作など)を行うフック。
- 依存リストによって、実行タイミングや頻度を制御できる。
- クリーンアップ関数でリソースの解放やサブスクリプション解除を管理する。
- レンダリング後に非同期で実行されるが、
useLayoutEffect
はレンダリング前に実行される。 - 非同期処理は
useEffect
内でasync
関数を呼び出す形で実装する。
質問
1. useEffect
とは何ですか?
useEffect
は、副作用を処理するためのReactフックです。副作用とは、Reactのレンダリングの外で発生する処理のことです(例:データ取得、タイマー、外部リソースへのアクセスなど)。
コンポーネントがレンダリングされるたびに実行されるため、ライフサイクルメソッド(componentDidMount
、componentDidUpdate
、componentWillUnmount
)のような役割を持ちます。
useEffect(() => {
// 副作用の処理(例:APIからデータを取得)
fetchData();
return () => {
// クリーンアップ処理(例:タイマーのクリア)
};
}, [依存リスト]); // 依存リストに指定された値が変わるたびに実行
2. useEffect
の依存リストとは?
useEffect
の第2引数として渡す配列が依存リストです。このリストに指定した変数が変更されたときに、useEffect
が再実行されます。
依存リストを空にすると、useEffect
は初回レンダリング時に一度だけ実行されま(componentDidMount
に相当)。
// 依存リストが空の例
useEffect(() => {
console.log("This runs only on mount");
}, []);
3. 依存リストを使わない場合の注意点
依存リストを省略(しょうりゃく)すると、コンポーネントが再レンダリングされるたびにuseEffect
が実行されます。
不必要な再実行が発生し、パフォーマンスに悪影響を及ぼす可能性があるため、明確な理由がない限り依存リストを指定するのが一般的です。
「明確な理由」とは、依存する変数がなく、コンポーネントがレンダリングされるたびに必ず処理を実行したい場合です。例えば、スクロール位置のログ出力やレンダリングごとに特定のイベントを発生させるなど、状態の変化に関係なく処理が必要な場合が該当します。また、タイマーの設定や外部のサードパーティーライブラリを扱う場合、毎回再実行する必要があるかもしれません。
4. クリーンアップ処理とは?
useEffect
は、クリーンアップ処理を返すことができます。この処理は、コンポーネントがアンマウントされるとき、または依存する値が変更される前に実行されます。
主に、サブスクリプションの解除やタイマーのクリアなど、リソースを解放するために使います。
useEffect(() => {
const interval = setInterval(() => {
console.log("Tick");
}, 1000);
return () => {
// アンマウント時や依存する値が変わる前に呼ばれる
clearInterval(interval);
};
}, []);
5. useEffect
が実行されるタイミングは?
useEffect
は、レンダリング後に実行されます。これは、ユーザーが画面上で変更を見た後に、副作用処理が実行されるという意味です。
同期的な処理ではなく、ReactがDOMを更新してから実行される非同期的な処理です。
6. useEffect
の依存関係が変わるたびに実行されるのはなぜですか?
useEffect
が依存リストに基づい て再実行される理由は、Reactがコンポーネントの状態やpropsに基づいた副作用処理を最新に保つためです。
Reactは依存リスト内の変数をトラッキングし、コンポーネントが再レンダリングされるたびに依存リストに含まれる値の現在の状態と、前回のレンダリング時の値を比較しています。もし依存リスト内の値に変化があれば、ReactはそのuseEffect
を再実行します。これにより、最新のデータや状態に基づいて処理が行われます。
useEffect(() => {
// countが変わるたびに実行される
console.log(`Count is now ${count}`);
}, [count]);
7. useEffect
とuseLayoutEffect
の違いは何ですか?
useEffect
は、レンダリング後に非同期で実行されますが、useLayoutEffect
は、レンダリングが画面に反映される前に実行されます。
useLayoutEffect
は、レイアウトに直接影響を与える処理(DOMの測定や同期的なレイアウト変更)に使われます。通常は、useEffect
を使うことが推奨されます。
8. useEffect
内で非同期処理を行う場合のベストプラクティスは?
useEffect
のコールバック関数自体をasync
にすることはできませんが、その中で非同期関数を呼び出すことは可能です。
非同期処理を行う場合は、関数を定義してその中でasync
/await
を使います。
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
setData(data);
};
fetchData();
}, []);