反应状态正确更新,除了内部游戏循环功能
React state updated properly except inside gameloop function
我有这个非常简单的 React 代码,它 使用 useState 挂钩 声明了一个名为 money 的状态变量。
然后我使用useEffect hook触发一个游戏循环开始一次。
在这个游戏循环中,我只是增加了 money 状态变量的值。
import React, { useState, useEffect } from "react";
export default function Game() {
// declare one state variable
const [money, setMoney] = useState(100);
// start gameloop
useEffect(() => {
let anim = requestAnimationFrame(gameloop);
return () => {
cancelAnimationFrame(anim);
};
}, []);
function gameloop() {
setMoney(money => money + 1);
console.log(money); // always returns 100
requestAnimationFrame(gameloop);
}
return (
<div>
<div>{money}</div>
</div>
);
}
UI 正确更新,当我使用 React 开发工具查看它时,状态也会更新。
然而,在 gameloop 函数中,当我执行 console.log(money);
它总是打印 100.
似乎如果我尝试读取 gameloop 函数中的 money 变量,它总是初始状态而不是真实状态。
知道我在这里做错了什么吗?
你没有做错任何事。这是因为 React 状态是异步更新的。这意味着当您想要控制台记录 money
变量的状态时,状态尚未更新。你可以做的是从 useEffect
函数中记录它,像这样:
useEffect(() => {
let anim = requestAnimationFrame(gameloop);
console.log(money);
return () => {
cancelAnimationFrame(anim);
};
}, [money]);
gameloop
函数是在 money
的值为 100
时在初始渲染中声明的。正是这个相同的函数,在其范围内 money
变量仍然是 100,在每个帧上被调用,而不是在每个渲染上创建的函数(它在 [= 中具有 "freshest" 值12=]).
要同步两个计划(rAF 与 React),您可以使用 useRef
挂钩。例如,在每个渲染器上重新创建游戏循环:
let gameloop = useRef();
gameloop.current = function() {
...
requestAnimationFrame(gameloop.current);
}
实际上,useRef
挂钩在函数组件上创建 a sort of instance property。
我有这个非常简单的 React 代码,它 使用 useState 挂钩 声明了一个名为 money 的状态变量。
然后我使用useEffect hook触发一个游戏循环开始一次。
在这个游戏循环中,我只是增加了 money 状态变量的值。
import React, { useState, useEffect } from "react";
export default function Game() {
// declare one state variable
const [money, setMoney] = useState(100);
// start gameloop
useEffect(() => {
let anim = requestAnimationFrame(gameloop);
return () => {
cancelAnimationFrame(anim);
};
}, []);
function gameloop() {
setMoney(money => money + 1);
console.log(money); // always returns 100
requestAnimationFrame(gameloop);
}
return (
<div>
<div>{money}</div>
</div>
);
}
UI 正确更新,当我使用 React 开发工具查看它时,状态也会更新。
然而,在 gameloop 函数中,当我执行 console.log(money);
它总是打印 100.
似乎如果我尝试读取 gameloop 函数中的 money 变量,它总是初始状态而不是真实状态。
知道我在这里做错了什么吗?
你没有做错任何事。这是因为 React 状态是异步更新的。这意味着当您想要控制台记录 money
变量的状态时,状态尚未更新。你可以做的是从 useEffect
函数中记录它,像这样:
useEffect(() => {
let anim = requestAnimationFrame(gameloop);
console.log(money);
return () => {
cancelAnimationFrame(anim);
};
}, [money]);
gameloop
函数是在 money
的值为 100
时在初始渲染中声明的。正是这个相同的函数,在其范围内 money
变量仍然是 100,在每个帧上被调用,而不是在每个渲染上创建的函数(它在 [= 中具有 "freshest" 值12=]).
要同步两个计划(rAF 与 React),您可以使用 useRef
挂钩。例如,在每个渲染器上重新创建游戏循环:
let gameloop = useRef();
gameloop.current = function() {
...
requestAnimationFrame(gameloop.current);
}
实际上,useRef
挂钩在函数组件上创建 a sort of instance property。