【发布时间】:2021-08-27 19:22:11
【问题描述】:
我已经使用 React 几年了,其中包含功能组件和钩子。我发现最令人沮丧的事情与传递回调有关。我有两个担忧:
-
如果一个元素从父级接收到回调,它就不能在事件侦听器或 onEvent 字段或 setTimeout/setInterval 中真正使用该函数,因为在父级重新渲染时可能会重新定义传递的函数。
-
在每次渲染时生成的函数(如箭头函数)并传递给子元素会破坏 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