Javascript 函数不使用钩子指向状态变量的更新值
我目前正在将react应用程序从setState重构为hooks。我不明白为什么状态变量没有改变。以下是一个例子:Javascript 函数不使用钩子指向状态变量的更新值,javascript,reactjs,Javascript,Reactjs,我目前正在将react应用程序从setState重构为hooks。我不明白为什么状态变量没有改变。以下是一个例子: import React, { useState, useEffect } from 'react'; function Hook() { const [num, setNum] = useState(1); useEffect(() => { window.addEventListener("mousemove", logNum);
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;
但输出如下所示:
为什么没有记录更新的num变量?
logNum()函数不应该总是指向状态的当前值吗?这就是为什么效果依赖必须是详尽的
logNum
在num
上闭包,因此在每个重新渲染器上都有一个包含新值的新num
变量,并有一个新的logNum
函数记录该值。但是,效果只初始化一次,因此它只知道第一个logNum
。因此,您必须添加logNum
作为依赖项,以便在num
发生变化时更新效果,从而logNum
发生变化:
useEffect(() => {
window.addEventListener("mousemove", logNum);
}, [logNum]);
您会注意到效果不正确,还应该添加一个removeEventListener
return () => window.removeEventListener("mousemove", logNum);
现在,如果您调试这段代码,您会注意到效果会在每次重新渲染时触发。这是因为无论num
是否更改,在每次重新加载时都会创建一个新的logNum
函数。为了防止出现这种情况,可以使用使logNum
引用稳定:
const logNum = useCallback(() => console.log(num), [num]);
所有这一切的替代方法是引用:
要在控制台中显示
console.log()
,您需要将其放置或使用函数的return()
语句引用它。这就是为什么console.log
ged中的handleToggle
会被返回的原因。@mwamiTovi-um。。。不?
const logNum = useCallback(() => console.log(num), [num]);
const actualNum = useRef(num);
// that works no matter when and how this is executed
console.log(actualNum.current);