对使用React钩发现的解决方案的性能的担忧



我想揭露我对钩子的担忧。

虽然使用挂钩用于学习目的进行重构/重写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用于值,甚至可以将其用于事件处理程序中调用的函数。这不是更清洁的路径,但是您可以使它起作用。

最新更新