createEffectWithTarget
源码
ts
import type { DependencyList, EffectCallback, useEffect, useLayoutEffect } from 'react'
import { useRef } from 'react'
import useUnmount from '../useUnmount'
import depsAreSame from './depsAreSame'
import type { BasicTarget } from './domTarget'
import { getTargetElement } from './domTarget'
// 创建一个事件的副作用函数
const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayoutEffect) => {
/**
*
* @param effect
* @param deps
* @param target target should compare ref.current vs ref.current, dom vs dom, ()=>dom vs ()=>dom
*/
// 定义一个副作用函数hooks
const useEffectWithTarget = (
effect: EffectCallback,
deps: DependencyList,
target: BasicTarget<any> | BasicTarget<any>[]
) => {
// 初始化的标识
const hasInitRef = useRef(false)
const lastElementRef = useRef<(Element | null)[]>([])
const lastDepsRef = useRef<DependencyList>([])
const unLoadRef = useRef<any>()
// 传入的副作用hook
useEffectType(() => {
// 判读是不是数组
const targets = Array.isArray(target) ? target : [target]
// 获取target的dom
const els = targets.map((item) => getTargetElement(item))
// init run 初始化
if (!hasInitRef.current) {
hasInitRef.current = true
lastElementRef.current = els
lastDepsRef.current = deps
unLoadRef.current = effect()
return
}
if (
els.length !== lastElementRef.current.length ||
!depsAreSame(els, lastElementRef.current) ||
!depsAreSame(deps, lastDepsRef.current)
) {
unLoadRef.current?.()
lastElementRef.current = els
lastDepsRef.current = deps
unLoadRef.current = effect()
}
})
// 组件卸载的时候执行
useUnmount(() => {
unLoadRef.current?.()
// for react-refresh
hasInitRef.current = false
})
}
return useEffectWithTarget
}
export default createEffectWithTarget