为了账号安全,请及时绑定邮箱和手机立即绑定

react useState落后一步的问题

react useState落后一步的问题

慕码人8056858 2022-11-11 13:49:41
我正在尝试将我从 Udemy 学到的 Javascript 游戏转换为反应应用程序。它显然称为 Pig-Game。您可以掷骰子并将其值添加到您的银行中,直到您击中 1,然后轮到您的对手掷骰子。您可以在轮到您之前持有该价值并将其添加到您的总数中。我为“btn-roll”编写了一个函数来更新骰子并将其值添加到我的状态中。这是代码(排除不必要的部分):const App = () => {  const [dice, setdice] = useState(null);  const [current, setCurrent] = useState(0);  const [activePlayer, setactivePlayer] = useState(0);  const diceHandler = () => {    if (dice !== 1) {      setdice(() => {        const _dice = (Math.floor(Math.random() * 6) + 1);        setCurrent(current + _dice);        console.log(_dice);        return _dice;      }      );    } else {      activePlayer === 0 ? setactivePlayer(1) : setactivePlayer(0);      setdice(() => {        setCurrent(0);        return null;      })    }  } return (      <button className="btn-roll" onClick={diceHandler}><i className="ion-ios-loop"></i>Roll dice</button>      {dice ?        <img src={require(`./dice-${dice}.png`)} alt="Dice" className="dice" /> :        <></>      }  );} 第一个问题是“骰子”和“电流”落后了一步。每次我单击按钮时,它都会显示随机骰子图片,但骰子和电流的实际值落后 1 步。我用你目前看到的代码修复了它。现在的问题是,一旦我点击“1”,它会将值添加到当前,然后我必须再次单击,以便启动“setCurrent(0)”并切换 activePlayer。我也试过这个功能,但结果是一样的:  const diceHandler = () => {    setdice(() => {      if (dice !== 1) {        const _dice = (Math.floor(Math.random() * 6) + 1);        setCurrent(current + _dice);        console.log(_dice);        return _dice;      } else {        activePlayer === 0 ? setactivePlayer(1) : setactivePlayer(0);        setdice(() => {          setCurrent(0);          return null;        })      }    }    );  }我想知道我现有的功能(用于更新状态)是否有更好的解决方案以及为什么我必须再次单击该按钮。我使用 Hooks 完全错误吗?提前致谢
查看完整描述

2 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

您也许可以稍微简化该逻辑。


 const diceHandler = () => {

   const _dice = Math.floor(Math.random() * 6) + 1;

   

   if (_dice !== 1) {

     setCurrent(current + _dice);

     setdice(_dice);

   } else {

     setactivePlayer(activePlayer === 0 ? 1 : 0);

     setCurrent(0);

     setdice(0);

   }

 };

请注意如何使用三元运算符来更新 activePlayer。在状态设置器中使用回调函数有时是必要的,但在这里似乎没有必要。


查看完整回答
反对 回复 2022-11-11
?
富国沪深

TA贡献1790条经验 获得超9个赞

希望下面的代码对你有帮助!


 const App = () => {

      const [dice, setdice] = useState(null);

      const [current, setCurrent] = useState(0);

      const [activePlayer, setactivePlayer] = useState(0);


    const stateUpdater = _dice => {

      console.log(dice);

      if (dice !== 1) {

        setCurrent(current + _dice);

        console.log("dice value " + _dice);

      } else {

        console.log("Dice value is now one!", dice);

        activePlayer === 0 ? setactivePlayer(1) : setactivePlayer(0);

        setCurrent(0);

        setdice(null);

      }

    };


    const diceHandler = () => {

      let _dice = Math.floor(Math.random() * 6) + 1;

      setdice(_dice, stateUpdater(dice));

    };


    return (


     <button className="btn-roll" onClick={diceHandler}><i className="ion-ios-loop"></i>Roll dice</button>

     {dice ?

      <img src={require(`./dice-${dice}.png`)} alt="Dice" className="dice" /> :

    <></>

  }

  );

};

diceHandler 函数只负责生成 dice 的新值并将其更新到 dice 挂钩。


一旦钩子更新,就会调用回调,它的职责是在需要的地方更新值并进一步推进游戏。


它之前不能工作的原因是 setState 函数是异步的并且有延迟。这就是为什么更新变量的值可能不会立即反映在 setState 之后的语句中。


查看完整回答
反对 回复 2022-11-11
  • 2 回答
  • 0 关注
  • 114 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信