まず、useEffect
の書き方。
// 第一引数に関数を渡す
useEffect(() => {
// 実行させたい処理を記述する
return () => {
// クリーンアップとして実行したい処理を記述する(省略可)
}
// 第二引数はuseEffectに渡したコールバック関数を実行したい場合に記述
// 空配列だと初回のみ実行[]
},[])
非同期関数をuseEffect内で直接定義しない
useEffect
内で非同期関数を直接定義することはできません。 useEffect
のコールバック関数は同期的に実行されるため、非同期処理を行う場合は、useEffect
内で非同期関数を呼び出す必要があります。
useEffect(() => {
// 非同期関数を定義
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
// データをセットする処理
setData(data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
// 非同期関数を呼び出す
fetchData();
}, []);
クリーンアップ処理を考慮する
非同期処理が完了する前にコンポーネントがアンマウント(DOMから削除)されると、状態更新時にエラーが発生することがあります。画面表示は無く、コンソールを見ると一度実行した処理が動き続けていてバグやメモリに多大な負荷がかかるなどです。
クリーンアップ関数は、useEffect
の戻り値として関数を返します。
useEffect(() => {
// 副作用の処理
return () => {
// クリーンアップ処理
};
}, []);
また、クリーンアップ関数はコンポーネントがアンマウントされるか、依存配列の値が変わるたびに実行されます。これにより、古い副作用を解除し新しい副作用を適応することができるのです。
以下、クリーンアップ処理を考慮した例です。
import React, { useEffect, useState } from 'react';
const DataFetchingComponent = () => {
const [data, setData] = useState(null); // データの状態を管理
const [isMounted, setIsMounted] = useState(true); // マウント状態を追跡
useEffect(() => {
const fetchData = async () => {
try {
// APIリクエストを実行
const response = await fetch('https://api.example.com/data');
const result = await response.json();
// コンポーネントがマウントされている場合のみ状態を更新
if (isMounted) {
setData(result);
}
} catch (error) {
console.error('Error fetching data:', error);
}
};
// 非同期関数の呼び出し
fetchData();
// クリーンアップ関数を返す
return () => {
// コンポーネントがアンマウントされたことを示すためのフラグを更新
setIsMounted(false);
};
}, []); // 空の依存配列なのでコンポーネントのマウント時にのみ実行される(初回のみ実行される)
// データがまだロードされていない場合のローディング表示
if (!data) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
export default DataFetchingComponent;
以上です。他にも useEffectの依存配列[]
が注意点として挙げられますが、また躓いたら記事を書こうと思います。