Reactjs 状态变量不更新

时间:2021-07-20 22:52:21

标签: reactjs react-hooks

我正在尝试在 React 中制作一个简单的国际象棋游戏,并尝试在使用 React 钩子的函数组件中这样做。为了移动棋子,玩家必须点击他们想要移动的棋子,然后点击想要移动的棋子。以下是我的电路板组件的片段:

const Board = () => {
    const [clicked, setClicked] = useState(false);
    const [from, setFrom] = useState("");
    const [to, setTo] = useState("");
    ...

    const clickHandler = (i, j) => {
        if (!clicked) {
            setFrom('some_value');
            setClicked(true);
            ...
        } else {
            setTo('some_value');
            ...
            setClicked(false);
        }
        console.log(from + ', ' + to);
    }
    ...

问题是由于 tofrom 状态变量没有在我想要的时候更新。控制台输出最终看起来像:

, 
some_value, 
some_value, some_value

即使 console.log()setFrom()/setTo() 调用之后,to 和 from 值仅在下一次点击事件时更新。

我很确定 useState 不是我想在这里使用的钩子,但是在尝试了 useRefuseReducer 并遇到了类似的情况后,我一头雾水关于处理这种情况的最佳方法是什么。

3 个答案:

答案 0 :(得分:0)

局部变量在组件渲染开始时分配时设置。而且 React 状态更新是异步的,这意味着您的组件将在几毫秒后使用新值重新渲染。

因此,如果您将 console.log(from + ', ' + to); 移到点击处理程序之外,它将在下一次渲染时执行,您应该注销您期望的值。

const Board = () => {
    const [clicked, setClicked] = useState(false);
    const [from, setFrom] = useState("");
    const [to, setTo] = useState("");

    const clickHandler = (i, j) => {
        if (!clicked) {
            setFrom('some_value');
            setClicked(true);
            ...
        } else {
            setTo('some_value');
            ...
            setClicked(false);
        }
    }

    // This should now log what you expect.
    console.log(from + ', ' + to);

    //...

}

<块引用>

“我想我应该在帖子中概述这一点,但为了进行计算以验证移动,我对 else 子句中的 tofrom 变量有逻辑。”

>

如果您需要在点击处理程序中设置的更新值,那么您拥有这些值,因为您只是设置了它们。您无需等待状态更新。

    const clickHandler = (i, j) => {
        const newFrom = 'some_value';
        const newTo = 'some_other_value';
        if (!clicked) {
            setFrom(newFrom);
            setClicked(true);
        } else {
            setTo(newTo);
            setClicked(false);
        }

        console.log(calculateDistance(newFrom, newTo))
    }

或者,当这两个变量发生变化时,您可以改用 useEffect 来触发一些代码。

const Board = () => {
  //... state hooks

  useEffect(() => {
    console.log(calculateDistance(from, to))
  }, [from, to])
  
  const clickHandler = //...
}

这将在 fromto 来自的状态被分配新值的任何渲染之后运行。

答案 1 :(得分:0)

捕获更新状态的唯一正确方法是 useEffect 钩子,因为您正在使用功能组件。 setState 是异步操作,它会在所有同步代码之后执行。 useEffect 钩子会在状态更改后立即启动,因此您可以确保捕获最新的状态值。

// this will never show you updated state:
setState(value) // this line will be executed later
console.log(value) // shows the old state

// that's how you catch new state:
useEffect(() => {
  console.log(`The new state value is ${value}`)
}, [value])

答案 2 :(得分:0)

经过更多研究,我得出的解决方案是在组件主体中使用 $('#content').load('http://localhost/HTML/acerca_de.html' , '#content'); 钩子来执行移动验证和板更新,useEffect 是依赖项数组的唯一成员。

to