如果您知道对象的形状,使用JSON.stringify()
或任何深度比较方法可能效率低下。您可以编写自己的effect hook,根据自定义相等函数的结果触发回调。
useEffect
通过检查依赖数组中的每个值是否与上一次渲染中的实例相同来工作。如果其中一个不同,则执行回调。因此,我们只需要使用useRef
保留我们感兴趣的数据的实例,并仅在自定义相等检查返回false
时分配新实例以触发effect。
function arrayEqual(a1: any[], a2: any[]) {
if (a1.length !== a2.length) return false;
for (let i = 0; i < a1.length; i++) {
if (a1[i] !== a2[i]) {
return false;
}
}
return true;
}
type MaybeCleanUpFn = void | (() => void);
function useNumberArrayEffect(cb: () => MaybeCleanUpFn, deps: number[]) {
const ref = useRef<number[]>(deps);
if (!arrayEqual(deps, ref.current)) {
ref.current = deps;
}
useEffect(cb, [ref.current]);
}
使用方法
function Child({ arr }: { arr: number[] }) {
useNumberArrayEffect(() => {
console.log("run effect", JSON.stringify(arr));
}, arr);
return <pre>{JSON.stringify(arr)}</pre>;
}
向前迈进一步,我们还可以通过创建一个接受自定义相等性函数的效果钩子来重复使用这个钩子。
type MaybeCleanUpFn = void | (() => void);
type EqualityFn = (a: DependencyList, b: DependencyList) => boolean;
function useCustomEffect(
cb: () => MaybeCleanUpFn,
deps: DependencyList,
equal?: EqualityFn
) {
const ref = useRef<DependencyList>(deps);
if (!equal || !equal(deps, ref.current)) {
ref.current = deps;
}
useEffect(cb, [ref.current]);
}
使用方法
useCustomEffect(
() => {
console.log("run custom effect", JSON.stringify(arr));
},
[arr],
(a, b) => arrayEqual(a[0], b[0])
);
演示
![编辑59467758 /将数组传递给useEffect依赖项列表](https://codesandbox.io/static/img/play-codesandbox.svg)
useEffect(() => { console.log(outcomes) }, [...outcomes])
- hazardous