简体   繁体   English

为什么我的 React 应用程序中的 console.logs 和 UI 没有显示相同的状态变量?

[英]Why do the console.logs and UI in my React app not show the same state variable?

In thiscoin flipping program , there is a delay in the updated state.flipResult and state.coinURL variables being printed to console (they are always a click behind what is shown in the UI).在这个硬币翻转程序中,更新的 state.flipResult 和 state.coinURL 变量被打印到控制台有一个延迟(它们总是在 UI 中显示的后面点击)。

I'm sure it has something to do with setState updates being asynchronous.我确定它与异步的 setState 更新有关。 How then, can I "force" a state update and rerender?那么,我如何“强制”状态更新并重新渲染?

I've seen examples of passing prevState to the setState function in order to force an update to a counter, for instance, but in this instance the flipResult and coinURL ( both "heads" or "tails") are not based on the previous state.例如,我见过将 prevState 传递给 setState 函数以强制更新计数器的示例,但在这种情况下,flipResult 和 coinURL(“头”或“尾”)不是基于先前的状态. I could find a way to toggle between heads and tails using prevState, but I might also want, in future, to "force" an instant state update based on a user's input or selection, unrelated to previous state.我可以找到一种使用 prevState 在正面和背面之间切换的方法,但将来我可能还希望根据用户的输入或选择“强制”即时状态更新,与之前的状态无关。 Is there a way to do this?有没有办法做到这一点?

Many thanks in advance for any help!非常感谢您的帮助!

Here's the code:这是代码:

import React, { Component } from "react";

import "./styles.css";

class App extends Component {
  state = {
    flipResult: "",
    coinURL: ""
  };

  flipCoin = () => {
    let number = Math.floor(Math.random() * 100) + 1;

    if (number <= 50) {
      this.setState( { flipResult: "heads", coinURL: "heads" });
    } else if (number >= 51) {
      this.setState({ flipResult: "tails", coinURL: "tails" });
    }
    console.log("flipResult is " + this.state.flipResult);
    console.log("flipResult is " + this.state.coinURL);
  };

  render() {
    return (
      <div>
       <h2> Flip a coin! </h2>
        <br />
        <button onClick={this.flipCoin}> Flip! </button>
        <br />

        {this.state.flipResult ? (
          <div>
            The result is {this.state.flipResult}.
            <br />
            <br />
            <img
              src={`./img/${this.state.coinURL}.jpg`}
              alt="coin"
              style={{ width: "200px", height: "auto" }}
            />
          </div>
        ) : (
          <div> No result yet! </div>
        )}
      </div>
    );
  }
}

export default App;


Web app can be found here - https://codesandbox.io/s/flipcoin-zj9sl?file=/src/App.js可以在此处找到 Web 应用程序 - https://codesandbox.io/s/flipcoin-zj9sl?file=/src/App.js

setState() does not always immediately update the component. setState() 并不总是立即更新组件。 It may batch or defer the update until later.它可能会批量更新或推迟更新。 This makes reading this.state right after calling setState() a potential pitfall.这使得在调用 setState() 之后立即读取 this.state 成为一个潜在的陷阱。 Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied相反,请使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),这两者都保证在应用更新后触发

So you can put console log in callback like this:因此,您可以像这样将控制台日志放入回调中:

  this.setState({ flipResult: "heads", coinURL: "heads" }, () => {
    console.log("flipResult is " + this.state.flipResult);
  });

the problem is that you are not understanding that setState is an asynchronous event, therefore you can not trust that calling console.log(this.state.SOMETHING) will give you the new state.问题是你不理解setState是一个异步事件,因此你不能相信调用console.log(this.state.SOMETHING)会给你新的状态。

the function setState accepts as second parameter a callback function, so you can do something like this:函数setState接受回调函数作为第二个参数,因此您可以执行以下操作:

flipCoin = () => {
    let number = Math.floor(Math.random() * 100) + 1;

    if (number <= 50) {
      this.setState( { flipResult: "heads", coinURL: "heads" }, this.logInformation);
    } else if (number >= 51) {
      this.setState({ flipResult: "tails", coinURL: "tails" }, this.logInformation);
    }
    
};

logInformation(){
  console.log("flipResult is " + this.state.flipResult);
  console.log("flipCoin is " + this.state.coinURL);
} 

so after the state has been set, it will call your function and you will be able to see the new state.因此在设置状态后,它将调用您的函数,您将能够看到新状态。

NOTE: notice that when you click for the first time it shows empty, on the second click it will show the previous state, this is because as I explained, it is showing the unset value.注意:请注意,当您第一次单击时它显示为空,第二次单击时它将显示以前的状态,这是因为正如我所解释的,它显示的是未设置的值。

the whole code you posted would be the following:您发布的整个代码如下:

import React, { Component } from "react";

import "./styles.css";

class App extends Component {
  state = {
    flipResult: "",
    coinURL: ""
  };

  flipCoin = () => {
    let number = Math.floor(Math.random() * 100) + 1;

    if (number <= 50) {
      this.setState( { flipResult: "heads", coinURL: "heads" }, this.logInformation);
    } else if (number >= 51) {
      this.setState({ flipResult: "tails", coinURL: "tails" }, this.logInformation);
    }
    
  };

  logInformation(){
    console.log("flipResult is " + this.state.flipResult);
    console.log("flipCoin is " + this.state.coinURL);
  }

  render() {
    return (
      <div>
       <h2> Flip a coin! </h2>
        <br />
        <button onClick={this.flipCoin}> Flip! </button>
        <br />

        {this.state.flipResult ? (
          <div>
            The result is {this.state.flipResult}.
            <br />
            <br />
            <img
              src={`./img/${this.state.coinURL}.jpg`}
              alt="coin"
              style={{ width: "200px", height: "auto" }}
            />
          </div>
        ) : (
          <div> No result yet! </div>
        )}
      </div>
    );
  }
}

export default App;

import React, { Component } from "react";

import "./styles.css";

class App extends Component {
  state = {
    flipResult: "",
    coinURL: ""
  };

  flipCoin = async () => {
    let number = Math.floor(Math.random() * 100) + 1;

    if (number <= 50) {
      await this.setState( { flipResult: "heads", coinURL: "heads" });
    } else if (number >= 51) {
      await this.setState({ flipResult: "tails", coinURL: "tails" });
    }
    console.log("flipResult is " + this.state.flipResult);
    console.log("flipcoin png  is " + this.state.coinURL);
  };

  render() {
    return (
      <div>
       <h2> Flip a coin! </h2>
        <br />
        <button onClick={this.flipCoin}> Flip! </button>
        <br />

        {this.state.flipResult ? (
          <div>
            The result is {this.state.flipResult}.
            <br />
            <br />
            <img
              src={`./img/${this.state.coinURL}.jpg`}
              alt="coin"
              style={{ width: "200px", height: "auto" }}
            />
          </div>
        ) : (
          <div> No result yet! </div>
        )}
      </div>
    );
  }
}

export default App;



What Have I done我做了什么

as updating a state is an async process so we can make the parent function async and wait for updating state by await command由于更新状态是一个异步过程,因此我们可以使父函数异步并通过await命令等待更新状态

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反应useEffect state变量console.logs不同的值连续 - React useEffect state variable console.logs different values consecutively 在 render() 中反应组件 console.logs 2 次 - React component console.logs 2 times in render() 为什么Generator中的console.logs会以这种顺序出现? - Why console.logs in generator appears in such order? 为什么 console.logs 与中呈现的 output 不匹配<text>在这个基本的 React Native Expo 项目中的表达式</text> - Why does console.logs does not matched the output rendered in <Text> expression in this basic React Native Expo Project 删除了库中的 console.logs 仍然显示在客户端 - Removed console.logs in library still show on the client 为什么这个 function 返回 undefined 但 console.logs 正确答案? - Why does this function return undefined but console.logs the correct answer? 为什么我的状态显示在我的控制台日志中而不是我的 HTML 中? - Why is my state showing up in my console logs but not my HTML? 如何在nodemon中隐藏黄色的console.logs - How to hide the yellow console.logs in nodemon Windows Vista Internet Explorer 9 console.logs - Windows vista Internet Explorer 9 console.logs VSCODE 未显示 javascript 功能 console.logs - VSCODE not showing javascript fuction console.logs
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM