从其他答案中汲取灵感,我一直在使用以下钩子
import React from 'react';
import IsEqual from 'lodash/isEqual';
/**
* The role of this function is to ensure that useEffect doesn't not
* fire unless the value of a varr (variable but "var" is a reserved word 😉)
* changes. For examples:
* const a = { 'hi': 5 }
* const b = { 'hi': 5 }
*
* a === b // false
* IsEqual(a, b) // true
*
* By default the React.useEffect(() => {}, [dependencies]) only does "===" but
* for cases where we only want useEffect to re-fire when the true value
* of a varr changes "IsEqual", we use this.
*
* @param varr: any
* @returns {function(): *}
*/
const useMostRecentImmutableValue = (varr) => {
let mostRecentValue = varr;
const mostRecentPointer = React.useRef(varr);
return () => {
// short circuit if "shallow equality"
if (mostRecentPointer.current === varr) {
return mostRecentValue;
}
// mostRecentValue only updates when the true value of varr changes
if (!IsEqual(varr, mostRecentPointer.current)) {
mostRecentValue = varr;
}
// mostRecentPointer changes every time "shallow equality" fails but
// after we've checked deep equality
mostRecentPointer.current = varr;
return mostRecentValue;
};
};
export default useMostRecentImmutableValue;
然后在一个钩子中,我会做这样的事情:
import useMostRecentImmutableValue from 'use-most-recent-immutable-value.hook';
const useMyHook = (foo = { 'hi': 5 }) => {
const mostRecentFoo = useMostRecentImmutableValue(foo);
React.useEffect(() => {
const unsubscribe = mySubscriptionFunction(mostRecentFoo);
return () => {
unsubscribe();
};
}, [mostRecentFoo]);
};
export default useMyHook;