【问题标题】:Problem with react useState falling behind one stepreact useState落后一步的问题
【发布时间】:2020-07-12 04:56:02
【问题描述】:

我正在尝试将我从 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 完全错误吗? 提前致谢

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    你也许可以稍微简化一下这个逻辑。

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

    【讨论】:

    • 非常感谢它解决了我的问题。我认为用实际的“骰子”设置“setdice”是错误的,不是吗?我认为这是我的程序中不同步变量的问题。
    【解决方案2】:

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

     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 hook。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      相关资源
      最近更新 更多