React Hooks useEffect: oldValuesとnewValuesの比較をマスターしよう
React Hooks useEffectにおけるoldValuesとnewValuesの比較方法
比較方法
- usePreviousカスタムフックを使う
usePrevious
は、前回の値を保持するカスタムフックです。このフックを使うことで、useEffect
内で前回と現在の値を簡単に比較できます。
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const previousCount = usePrevious(count);
if (count !== previousCount) {
// countが変わった時の処理
}
}, [count]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
- useRefと
JSON.parse(JSON.stringify())
を使う
useRef
を使って参照を作成し、JSON.parse(JSON.stringify())
を使って前回の値をディープコピーすることで、比較することができます。
const MyComponent = () => {
const [count, setCount] = useState(0);
const ref = useRef();
useEffect(() => {
if (ref.current === undefined) {
ref.current = count;
} else {
const previousCount = ref.current;
if (count !== previousCount) {
// countが変わった時の処理
}
ref.current = count;
}
}, [count]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
- useMemoと
useDeepCompareEffect
を使う
useMemo
とuseDeepCompareEffect
を使うことで、前回の値と現在の値をディープ比較できます。
import { useMemo, useDeepCompareEffect } from 'react';
const MyComponent = () => {
const [count, setCount] = useState(0);
const memoizedCount = useMemo(() => count, [count]);
useDeepCompareEffect(() => {
// memoizedCountが変わった時の処理
}, [memoizedCount]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
useEffect
内で前回と現在の値を比較するには、いくつかの方法があります。それぞれの特徴を理解して、状況に応じて使い分けてください。
usePreviousカスタムフックを使う
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const previousCount = usePrevious(count);
if (count !== previousCount) {
console.log(`カウントが${previousCount}から${count}に変わりました。`);
}
}, [count]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
useRefとJSON.parse(JSON.stringify())を使う
const MyComponent = () => {
const [count, setCount] = useState(0);
const ref = useRef();
useEffect(() => {
if (ref.current === undefined) {
ref.current = count;
} else {
const previousCount = ref.current;
if (count !== previousCount) {
console.log(`カウントが${previousCount}から${count}に変わりました。`);
}
ref.current = count;
}
}, [count]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
useMemoとuseDeepCompareEffectを使う
import { useMemo, useDeepCompareEffect } from 'react';
const MyComponent = () => {
const [count, setCount] = useState(0);
const memoizedCount = useMemo(() => count, [count]);
useDeepCompareEffect(() => {
console.log(`カウントが${memoizedCount}から${count}に変わりました。`);
}, [memoizedCount]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
実行結果
カウントが0から1に変わりました。
カウントが1から2に変わりました。
カウントが2から3に変わりました。
...
useEffect内でoldValuesとnewValuesを比較する他の方法
useStateとuseEffectの組み合わせ
useState
を使って前回と現在の値を保持し、useEffect
で比較する方法です。
const MyComponent = () => {
const [count, setCount] = useState(0);
const [previousCount, setPreviousCount] = useState(0);
useEffect(() => {
setPreviousCount(count);
}, [count]);
useEffect(() => {
if (count !== previousCount) {
console.log(`カウントが${previousCount}から${count}に変わりました。`);
}
}, [count, previousCount]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
LodashのisEqual
を使って、oldValuesとnewValuesをディープ比較する方法です。
import isEqual from 'lodash/isEqual';
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const previousCount = useRef(count).current;
if (!isEqual(count, previousCount)) {
console.log(`カウントが${previousCount}から${count}に変わりました。`);
}
ref.current = count;
}, [count]);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
自作のカスタムフックを使う
上記の方法を参考に、自作のカスタムフックを作成することもできます。
const useCompareValues = (initialValue) => {
const [value, setValue] = useState(initialValue);
const ref = useRef(initialValue);
useEffect(() => {
if (!isEqual(value, ref.current)) {
// 値が変わった時の処理
}
ref.current = value;
}, [value]);
return [value, setValue];
};
const MyComponent = () => {
const [count, setCount] = useCompareValues(0);
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
};
reactjs react-hooks