useTrackedEffect
作用
追踪是哪个依赖变化触发了 useEffect 的执行
原理
通过 uesRef 记录上一次依赖的值,并在当前执行的时候,判断当前依赖值和上次依赖值之间的 diff 值
源码
ts
import type { DependencyList } from 'react'
import { useEffect, useRef } from 'react'
type Effect<T extends DependencyList> = (
changes?: number[],
previousDeps?: T,
currentDeps?: T,
) => void | (() => void)
const diffTwoDeps = (deps1?: DependencyList, deps2?: DependencyList) => {
//Let's do a reference equality check on 2 dependency list.
//If deps1 is defined, we iterate over deps1 and do comparison on each element with equivalent element from deps2
//As this func is used only in this hook, we assume 2 deps always have same length.
return deps1
? deps1
.map((_ele, idx) => (!Object.is(deps1[idx], deps2?.[idx]) ? idx : -1))
.filter((ele) => ele >= 0)
: deps2
? deps2.map((_ele, idx) => idx)
: []
}
const useTrackedEffect = <T extends DependencyList>(effect: Effect<T>, deps?: [...T]) => {
// 通过 useRef 记录上一次依赖的值
const previousDepsRef = useRef<T>()
useEffect(() => {
// 通过 diffTwoDeps 计算出当前依赖和上一次依赖的changes
const changes = diffTwoDeps(previousDepsRef.current, deps)
// 上次依赖的值
const previousDeps = previousDepsRef.current
// 当前依赖的值赋值给上一次依赖的值
previousDepsRef.current = deps
return effect(changes, previousDeps, deps)
}, deps)
}
export default useTrackedEffect