除了在游戏循环功能内

我有一个非常简单的反应代码,使用useState钩子声明一个名为money的状态变量

然后我使用useEffect钩子触发一个游戏循环以开始一次

在这个游戏循环中,我只是简单地增加了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 dev工具查看状态时,状态也会更新。

但是,在gameloop函数中,当我执行console.log(money); 时,它始终会打印100

似乎,如果我尝试读取gameloop函数中的money变量,则它始终是初始状态,而不是真实状态。

任何关于我在这里做错什么的想法?

iCMS 回答:除了在游戏循环功能内

您没有做错任何事情。这是因为React状态是异步更新的。这意味着当您要控制台记录money变量的状态时,该状态尚未更新。您可以做的是通过useEffect函数将其记录下来,如下所示:

useEffect(() => {
    let anim = requestAnimationFrame(gameloop);
    console.log(money);    
    return () => {
      cancelAnimationFrame(anim);
    };
  },[money]);
,

在初始渲染中,gameloop的值为money时,声明了100函数。正是该函数的作用域money仍为100,它在每个帧上都被调用,而不是在每个渲染器上创建的函数(在{{1}中具有“最新鲜”的值) }。

要同步两个时间表(rAF与React),可以使用money钩子。例如,在每个渲染器上重新创建gameloop:

useRef

实际上,let gameloop = useRef(); gameloop.current = function() { ... requestAnimationFrame(gameloop.current); } 钩子在功能组件上创建了a sort of instance property

本文链接:https://www.f2er.com/2103385.html

大家都在问