useEffect 依存配列の違い
React の useEffect
は、コンポーネントがレンダリングされた後に副作用を実行するためのフックです。この副作用の実行タイミングを制御するために、依存配列(dependency array)という概念が用いられます。
依存配列がない場合
依存配列を指定しない場合、useEffect
のコールバック関数は毎回のレンダリング後に実行されます。これは、コンポーネントの状態やプロップスの変化に関わらず、すべてのレンダリングで副作用がトリガーされることを意味します。
依存配列に空の配列 []
を指定した場合、useEffect
のコールバック関数は初回レンダリング後にのみ実行されます。その後、コンポーネントが再レンダリングされても、副作用は実行されません。
- 空の依存配列
初回レンダリング後にのみ実行 - 依存配列なし
毎回のレンダリング後に実行
import { useEffect, useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
// 依存配列なし
useEffect(() => {
console.log('Effect without dependency array');
// この副作用は毎回のレンダリング後に実行されます
});
// 空の依存配列
useEffect(() => {
console.log('Effect with empty dependency array');
// この副作用は初回レンダリング後にのみ実行されます
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
解説
-
依存配列なし
useEffect
のコールバック関数が毎回のレンダリング後に実行されます。setCount
を呼び出してcount
を更新するたびに、コンポーネントが再レンダリングされ、副作用がトリガーされます。- これは、毎回のクリックで
Effect without dependency array
がコンソールに出力されることを意味します。
-
空の依存配列
- その後、
count
の値が変化しても、副作用は再度トリガーされません。 - これは、初回レンダリング時にのみ
Effect with empty dependency array
がコンソールに出力され、以降のクリックでは出力されないことを意味します。
- その後、
useEffect
の依存配列の制御に関する代替アプローチをいくつか紹介します。
useCallback を活用した最適化
useEffect
のコールバック関数内で高階関数を定義している場合、その関数が毎回再作成されることでパフォーマンスに影響が出る可能性があります。このような場合、useCallback
を使用して、関数をメモ化することができます。
import { useEffect, useState, useCallback } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
useEffect(() => {
// ここで handleClick を使用
}, [handleClick]);
// ...
}
useMemo を活用した最適化
複雑な計算やデータの加工が必要な場合、その結果を useMemo
を使ってメモ化することができます。
import { useEffect, useState, useMemo } from 'react';
function MyComponent() {
const [data, setData] = useState([]);
const processedData = useMemo(() => {
// 複雑なデータ処理
return data.map(item => {
// ...
});
}, [data]);
useEffect(() => {
// processedData を使用
}, [processedData]);
// ...
}
useRef を活用した状態の管理
useEffect
のコールバック関数内で、前回のレンダリングの状態を参照したい場合、useRef
を使用することができます。
import { useEffect, useRef, useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const prevCountRef = useRef(0);
useEffect(() => {
if (prevCountRef.current !== count) {
// 前回の count と比較して、何か処理を行う
}
prevCountRef.current = count;
}, [count]);
// ...
}
reactjs react-hooks use-effect