Javascript 函数不使用钩子指向状态变量的更新值

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);

我目前正在将react应用程序从setState重构为hooks。我不明白为什么状态变量没有改变。以下是一个例子:

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);