[英]Function not pointing to the updated value of state variable using hooks
I am currently refactoring a react app from setState to hooks.我目前正在重构一个从 setState 到 hooks 的 React 应用程序。 I can't understand why the state variables aren't changed.我不明白为什么 state 变量没有改变。 Here is an example:这是一个例子:
import React, { useState, useEffect } from 'react';
function Hook() {
const [num, setNum] = useState(1);
useEffect(() => {
window.addEventListener("mousemove", logNum);
}, []);
const logNum = () => {
console.log(num);
}
const handleToggle = () => {
if (num == 1) {
console.log('setting num to 2');
setNum(2);
} else {
console.log('setting num to 1');
setNum(1);
}
}
return (
<div>
<button onClick={handleToggle}>TOGGLE BOOL</button>
</div>
);
}
export default Hook;
When i click the button, I was expecting the output to be something like:当我点击按钮时,我期待 output 是这样的:
// 1
// setting num to 2
// 2
// setting num to 1
// 1
But the output look like this:但是 output 看起来像这样:
Why is the updated num variable not logged?为什么没有记录更新的 num 变量? Shouldn't the logNum() function always point to the current value of the state? logNum() function 不应该总是指向 state 的当前值吗?
That's why effect dependencies have to be exhaustive .这就是为什么效果依赖性必须是详尽无遗的。 Don't lie about dependencies . 不要在依赖关系上撒谎。
logNum
closures over num
, so on every rerender there is a new num
variable containing the new value, and a new logNum
function logging that value. logNum
在num
上关闭,因此在每次重新渲染时都有一个包含新值的新num
变量,以及一个记录该值的新logNum
function。 Your effect however gets initialized only once, thus it only knows the first logNum
.然而,您的效果只被初始化一次,因此它只知道第一个logNum
。 Therefore, you have to add logNum
as a dependency, so that the effect gets updated whenever num
and thus logNum
changes:因此,您必须添加logNum
作为依赖项,以便在num
和logNum
发生变化时更新效果:
useEffect(() => {
window.addEventListener("mousemove", logNum);
}, [logNum]);
You'll notice that your effect does not correctly clean up , you should add a removeEventListener
too.您会注意到您的效果没有正确清理,您也应该添加一个removeEventListener
。
return () => window.removeEventListener("mousemove", logNum);
Now if you debug this piece of code, you'll notice that the effect triggers on every rerender.现在,如果您调试这段代码,您会注意到效果会在每次重新渲染时触发。 That is because a new logNum
function gets created on every rerender, no matter wether num
changes or not.这是因为在每次重新渲染时都会创建一个新的logNum
function,无论num
是否发生变化。 To prevent that, you can useuseCallback
to make the logNum
reference stable:为防止这种情况,您可以使用useCallback
使logNum
引用稳定:
const logNum = useCallback(() => console.log(num), [num]);
An alternative to all of this would be to use a reference to the current state :所有这些的替代方法是使用对当前 state的引用:
const actualNum = useRef(num);
// that works no matter when and how this is executed
console.log(actualNum.current);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.