【问题标题】:New React hook for callbacks用于回调的新 React 钩子
【发布时间】:2021-08-27 19:22:11
【问题描述】:

我已经使用 React 几年了,其中包含功能组件和钩子。我发现最令人沮丧的事情与传递回调有关。我有两个担忧:

  1. 如果一个元素从父级接收到回调,它就不能在事件侦听器或 onEvent 字段或 setTimeout/setInterval 中真正使用该函数,因为在父级重新渲染时可能会重新定义传递的函数。

  2. 在每次渲染时生成的函数(如箭头函数)并传递给子元素会破坏 React.memo()。

我已经看到了一些有限的解决方案,例如 useEventListener(),但没有解决我关心的所有情况。

所以我编写了自己的钩子,我称之为 useHandler。与 useCallback 不同,它在输入更改时生成一个新函数,useHandler 总是返回相同的函数。这样,函数 case 可以使用 React.memo() 或 setInterval 或其他方式传递给元素。

父元素(React.memo 案例需要)或子元素(如果您担心传入的函数可能会更改)调用它。这是在父级中使用的示例:

const onClick = useHandler(event => {
  //Do whatever you want.  Reference useState variables or other values that might change,
})

<MyElement onClick={onClick} />

MyElement 现在总是获得相同的函数,但调用该函数将执行父元素中最新的代码。

这是子元素中的一个示例:

const reportBack = useHandler(props.reportBack)

useEffect(() => {
  setInterval(reportBack, 1000)
}, [reportBack])

间隔回调总是会调用从父级传来的当前reportBack。

对我来说唯一缺少的是我没有修改 React eslint 配置以识别 useHandler 的结果无法更改,因此如果从 useEffect 或类似的依赖项列表中省略,则不应生成警告。

最后,这是我的 onHandler 钩子的源代码:

export function useHandler(callback) {
  const callbackRef = useRef()
  callbackRef.current = callback
  return useRef((...args) => callbackRef.current(...args)).current
}

我的问题是:这个解决方案有什么缺陷吗?这是解决我的 React 回调问题的好方法吗?我没有发现任何更优雅的东西,但我很愿意相信我错过了一些东西。

谢谢。

【问题讨论】:

    标签: reactjs callback react-hooks


    【解决方案1】:

    我无法评论第二点,因为我没有使用过 React.memo,但第一点是我们有清理功能的原因。

    假设您有一个作为道具传递给组件的函数,并且您想将其用作事件侦听器。

    如果您将此侦听器附加到 useEffect 中,例如:window.addEventListener('someEvent', (event) =&gt; someFunctionPassedAsProp(event)) 然后 useEffect 可能看起来像:

    useEffect(() => {
      const handler = (event) => someFunctionPassedAsProp(event)
      window.addEventListener('someEvent', handler)
      return () => window.removeEventListener('someEvent', handler)
    }, [someFunctionPassedAsProp])
    

    类似地,您可以执行以下操作:

    useEffect(() => {
      const interval = setInterval(() => someFunctionPassedAsProp(), 1000)
      return () => clearInterval(interval)
    }, [someFunctionPassedAsProp])
    

    【讨论】:

      猜你喜欢
      • 2020-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 2021-02-14
      • 2021-05-08
      • 2020-02-08
      相关资源
      最近更新 更多