React useState落后一步的问题

时间:2020-07-11 19:25:04

标签: javascript reactjs react-hooks

我正在尝试将我从Udemy学到的Javascript游戏转换为React应用程序。它的名称显然是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;
        })
      }
    }
    );

  }

我想知道我现有的功能(用于更新状态)是否有更好的解决方案,为什么我必须再次单击该按钮。我使用挂钩完全错误吗? 预先感谢

2 个答案:

答案 0 :(得分:2)

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

 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。有时有必要在状态设置器中使用回调函数,但此处似乎没有必要。

答案 1 :(得分:1)

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

 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函数仅负责生成骰子的新值并将其更新为骰子挂钩。

挂钩更新后,将立即调用回调,其职责是在需要时更新值并进一步推进游戏。

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