useEffectとは
Reactコンポーネント内で副作用を実行するためのフックです。副作用とは、API呼び出し、データの取得、DOMの更新、タイマーの設定、イベントリスナーの登録など、コンポーネント自体のレンダリングには直接関係ないけど、アプリケーションに影響を与える処理です。
useEffect
は、第一引数に副作用として実行したい処理を、第二引数に依存配列を渡します。依存配列には副作用の実行に必要な変数を指定し、その配列内の変数が変更される度に副作用が実行されます。
useEffect(() => {
/* 第一引数に副作用として実行したい処理 */
console.log('副作用が実行されました')
},[依存配列])
実行されるタイミング
1: マウント(初回ロード)された時 componentDidMount
2: レンダリングされた時 componentDidUpdate
3: アンマウントされた時 componentWillUnmount
以下、データ取得の場合の例です↓
import React, { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios("https://api.example.com/data");
setData(result.data);
};
fetchData();
}, []);
return (
<div>
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
useEffect
を使用して非同期処理を実行し、取得したデータをuseState
を使ってコンポーネントの状態に保存しています。このように、データの取得をコンポーネントのレンダリングとは分離して実行できます。
他にもstate
の変更を監視して処理を実行します。
useEffect(() => {
if (count < 10) return;
console.log('countが10以上です')
}, [count]);
クリーンアップ関数
useEffect
クリーンアップはフックの関数であり、コンポーネントがアンマウントされる前に実行されます。そうすることで、メモリリークを防ぎ、アプリケーションのパフォーマンスを最適化できます。
例えば、購読など「定期的に外部データを読み込みする」ようにしていると、放置したままでは、そのページから移動しても定期的な読み込みが生きたままです。それをクリーンアップ関数を使って、useEffect
で設定した処理をアンマウント時に解除してあげます。
また、第二引数を空にすることでレンダリング毎に実行されますが、予期しないケースでuseEffect
が実行されてしまう可能性があるため、第2引数を空にすることはNGです。
第二引数の配列の中身を空にすると、初回のレンダリング後のみ実行されます。
useEffect(() => {
// 処理
}, [])
以下、クリーンアップ関数を使用した例です。
const [ count, setCount ] = useState(0);
useEffect(
() => {
const time = setInterval( // 1秒ごとに定期実行する関数を、最初のレンダリングのときにセット
() => {
console.log("1秒ごとに定期実行");
setCount((prevState) => prevState + 1);
}, 1000
);
return () => clearInterval(time); //クリーンアップ関数。定期実行する関数をリセット
},
[]
);
return (
<div className = {styles.main}>
<div>{count}</div>
</div>
)
useEffect
のクリーンアップ関数を設定しないと、ページ移動してもsetInterval
が実行され続け、メモリリークに繋がります。