我想揭露我对钩子的担忧。
虽然使用挂钩用于学习目的进行重构/重写React库(React-Numpad),但我一直被关键事件的EventListener实现。
在类中,这是通过在ComponentDidmount和ComponentWillunMount LifeCycles中添加addListener来完成的。
usekeypress钩
https://github.com/gpietro/reactro/react-numpad/blob/issue/8/numpad-visible-default/lib/lib/hooks/usekeypress.js
更新回调
numpad组件是具有值的状态
的父
https://github.com/gpietro/reaeact-numpad/blob/issue/8/numpad-visible-default/lib/lib/components/numpad.js#l93
挂钩用法
键盘组件是接收价值作为道具并致电的儿童 在键盘上更新为回调。如果使用效果(挂钩内部)具有空数组
,则不会更新此值
https://github.com/gpietro/reaectro/react-numpad/blob/issue/8/numpad-visible-default/lib/lib/elements/keypad.js#l70
现在,添加并删除了每个渲染添加程序。这不是以前发生的,而仅在安装或卸载组件时。
有与使用类的使用相同的行为?
您不需要在每个渲染中添加或删除事件侦听器,并且只能将它们与空数组一起使用作为第二个参数,而像以前一样添加一次。类似:
useEffect(() => {
// your didMount code here
return () => {
// your willUnmount code here
}
}, [])
问题
您这样做的问题是,由于功能仅运行一次,因此可以从中获得的值(例如Props或其他外部距离变量)不会随着它们的更改而更新。
作为一个例子:
const [foo, setFoo] = setState(1)
useEffect(() => {
const id = window.setInterval(() => console.log(foo), 1000)
return () => window.clearInterval(id)
}, [])
// ...
setFoo(2)
即使在调用setFoo之后,此代码也将始终打印1,因为该函数绑定到foo的旧值。
推荐解决方案
当您只需要根据自身和其他一些值继续更新某些状态时,最好的选择是将降低器与用户使用。您可以使用使用效果函数(或任何其他位置)中的调度,并将使用更新的状态调用还原器,从而使其可以阅读并根据需要进行更新。只需传递有关动作本身的任何新信息。
在您的使用情况下,您只需派遣相关事件信息,并与更新有关。
其他选项
React Events
如果您可以使用标准的React事件而不是任何AddEdeventListener,则无需考虑此问题,因为该功能将在每个渲染上更新,而无需采取任何操作。您可以将功能作为道具传递,以便它们也可以从子组件中使用。
refs
您可以使用REF,因为它们总是返回相同的对象,而不是创建新对象。这使得能够访问涉及当前值的任何功能。
示例:
const fooRef = useRef(1)
fooRef.current = foo
useEffect(() => {
const id = window.setInterval(() => console.log(fooRef.current), 1000)
return () => window.clearInterval(id)
}, [])
// ...
fooRef.current = 2
您可以将REF用于值,甚至可以将其用于事件处理程序中调用的函数。这不是更清洁的路径,但是您可以使它起作用。