Skip to content

useMemoizedFn

作用

持久化 function 的 Hook,理论上,可以使用 useMemoizedFn 完全代替 useCallback

在某些场景中,我们需要使用 useCallback 来记住一个函数,但是在第二个参数 deps 变化时,会重新生成函数,导致函数地址变化。

useMemoizedFn 会在 deps 变化时,返回一个新的函数,但是函数的地址不会变化。

原理

通过 useRef 保持 function 引用地址不变,并且每次执行都可以拿到最新的 state 值。

源码

ts
import { useMemo, useRef } from 'react'
import { isFunction } from '../utils'
import isDev from '../utils/isDev'

type noop = (this: any, ...args: any[]) => any

type PickFunction<T extends noop> = (
  this: ThisParameterType<T>,
  ...args: Parameters<T>
) => ReturnType<T>

function useMemoizedFn<T extends noop>(fn: T) {
  if (isDev) {
    if (!isFunction(fn)) {
      console.error(`useMemoizedFn expected parameter is a function, got ${typeof fn}`)
    }
  }

  // 通过 useRef 保持其引用地址不变,并且值能够保持值最新
  const fnRef = useRef<T>(fn)

  // why not write `fnRef.current = fn`?
  // https://github.com/alibaba/hooks/issues/728
  fnRef.current = useMemo(() => fn, [fn])

  // 通过 useRef 保持其引用地址不变,并且值能够保持值最新
  const memoizedFn = useRef<PickFunction<T>>()
  if (!memoizedFn.current) {
    // 返回的持久化函数,调用该函数的时候,调用原始的函数,并且保持 this 指向不变
    memoizedFn.current = function (this, ...args) {
      return fnRef.current.apply(this, args)
    }
  }

  return memoizedFn.current as T
}

export default useMemoizedFn

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