useEffect依赖数组中变量的比较问题
2020-07-02 本文已影响0人
penelope_2bad
- 利用useCompare做比较
https://zhuanlan.zhihu.com/p/86211675
React 对于各 hook 函数依赖数组中变量的比较都是严格比较(===),所以我们需要注意对象类型变量的引用。类似下面的情况应该尽量避免,因为每次 App 组件渲染,传给 Child 组件的 list 变量都是一个全新引用地址的数组。如果 Child 组件将 list 变量放入了某个 hook 函数的依赖数组里,就会引起该 hook 函数的依赖变动。
function App() {
const list = [1, 2, 3];
return (
<>
<Child list={list}></Child>
<Child list={[4, 5, 6]}></Child>
</>
);
}
上面这种情况多加注意还是可以避免的,但在某些情况下我们希望依赖数组中对象类型的比较是浅比较或深比较。在 componnetDidUpdate 声明周期函数中这确实不难实现,但在函数式组件中还是需要借助 useRef 函数。
例子:
import { isEqual } from 'lodash';
function useCampare(value, compare) {
const ref = useRef(null);
if (!compare(value, ref.current)) {
ref.current = value;
}
return ref.current;
}
function Child({ list }) {
const listArr = useCampare(list, isEqual);
useEffect(() => {
console.log(listArr);
}, [listArr]);
}
在该例子中,使用了一个 ref 变量,每次组件渲染时都会取之前的值与当前值进行自定义函数的比较,如果不相同,则覆盖当前值,最后返回 ref.current 值。从而实现了自定义依赖数组比较方法的功能。
- 重写useEffect
type DeepIsEqualType<TDeps = React.DependencyList> = (newDeps: TDeps, oldDeps: TDeps) => boolean;
export function useDeepEqualEffect<TDeps = React.DependencyList>(
effect: React.EffectCallback,
deps: TDeps,
compare: DeepIsEqualType<TDeps> = isEqual
) {
const oldDeps = React.useRef<TDeps | undefined>(undefined);
if (!oldDeps.current || !compare(deps, oldDeps.current as TDeps)) {
oldDeps.current = deps;
}
React.useEffect(effect, [oldDeps.current]);
}