我正在使用Hooks构建REACT App,现在在使用useMemo()和某些事件侦听器时遇到问题。我已经在CodeSandBox上准备了一个关于我的问题的更简单的演示:这是链接→https://codesandbox.io/s/mystifying-hertz-21jov?fontsize=14&hidenavigation=1&theme=dark

现在,让我解释问题出在哪里:我有使用buttonData计算的useMemo()。现在,让我们看一下控制台输出:
javascript - React.useMemo()和事件监听器-LMLPHP

首先,在第一次渲染时计算buttonData,并且buttonData.behavior等于test1。然后,当我输入按钮时,在onMouseEnterButton内部使用setTargetDOM:这将触发重新计算buttonData,因为setTargetDOM是其依赖项之一。
到目前为止,一切都很好:


在控制台的第一行,我们看到buttonData.behaviortest1;
在第二行中,我们看到输入onMouseEnterButton,现在buttonData.behaviortest1
在第三行中,我们看到,由于targetDOM已更改,因此我们再次计算了buttonData,现在buttonData.beavhior等于test2


现在,问题来了,我不明白的是!我可以以某种方式接受这样一个事实,即第四个控制台行告诉我buttonDat.behavior仍然是test1,因为我们仍处于更改targetDOM并因此触发buttonData进行更改的同一函数中(即使我期望甚至在第四行中也可以看到buttonData.behavior: test2

更糟糕的是,在onMouseMoveButton内部,我看到buttonData.behavior等于test1,而不是test2

问题很简单。为什么?我的意思是,我认为我可以这样实现test2,但是我想我这里缺少一些React Hook东西。

最佳答案

onMouseMoveButtononMouseEnterButton在第一个渲染上捕获buttonData.behavior,并且因为您从不更新事件侦听器,所以它们将始终引用buttonData.behavior的初始值

您可以做的是将buttonData.behavior添加到useLayoutEffect的依赖项数组中,每次buttonData.behavior更改时,它将运行返回的函数并删除先前的侦听器并添加新的侦听器

React.useLayoutEffect(() => {
  ...
}, [buttonData.behavior])


另外,状态更新是异步的,因此在第4行中,设置状态后您就不能真正地log更新状态

setTargetDOM(e.currentTarget);
// this will never the updated value because
// the state updater hasn't run yet
console.log(buttonData.behavior);

10-07 17:28