Skip to content

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

如有转载或 CV 的请标注本站原文地址