【发布时间】:2020-10-30 08:32:16
【问题描述】:
我有一个组件应该监听一些套接字事件。我将它们注册如下以避免事件侦听器的虚假注册/注销操作(socketListen 返回侦听器本身的破坏,因此已处理)。
useEffect(() => socketListen('name', newName => setName(newName)), []);
现在我有了更多此类听众,我想通过编写自定义钩子来摆脱样板代码
const useListener = (event, callback) => {
useEffect(() => socketListen(event, callback), [event, callback]);
};
然后用作
useListener('name', newName => setName(newName));
打算将重点放在执行的实际操作上,而不是 useEffect 调用上。
现在的问题是我将一个闭包(调用状态设置器setName)交给了我的自定义钩子,这意味着useListener 中的callback 在重新渲染时被更改,因此再次生成虚假的侦听器注册/注销。为了挽救,我可以将闭包包裹在 useCallback 中,但这会违背我减少代码混乱的最初目标。
我想我可以看到上述问题的功能原因(并希望在我的写作中传达这一点),但我想知道是否有一种方便的方法来编写一个辅助函数来完成我打算用 @987654329 完成的事情@ 没有额外的样板代码。我的实际代码使用了更复杂的闭包,但我希望这个示例足以确定我的问题。
【问题讨论】:
-
useListener('name', setName)。由useState()或useReducer()返回的setName已经被记忆,在这种情况下setName将等同于newName => setName(newName) -
我的例子在这方面表现不佳。我应该在
prefix is some prop or state的地方写newName => setName(prefix + newName),即闭包即使有明显的副作用也会改变功能。不过,您在下面的回答确实有很大帮助。
标签: react-hooks closures boilerplate