[英]React useEffect state variable console.logs different values consecutively
[英]Why do the console.logs and UI in my React app not show the same state variable?
在这个硬币翻转程序中,更新的 state.flipResult 和 state.coinURL 变量被打印到控制台有一个延迟(它们总是在 UI 中显示的后面点击)。
我确定它与异步的 setState 更新有关。 那么,我如何“强制”状态更新并重新渲染?
例如,我见过将 prevState 传递给 setState 函数以强制更新计数器的示例,但在这种情况下,flipResult 和 coinURL(“头”或“尾”)不是基于先前的状态. 我可以找到一种使用 prevState 在正面和背面之间切换的方法,但将来我可能还希望根据用户的输入或选择“强制”即时状态更新,与之前的状态无关。 有没有办法做到这一点?
非常感谢您的帮助!
这是代码:
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 应用程序 - https://codesandbox.io/s/flipcoin-zj9sl?file=/src/App.js
setState() 并不总是立即更新组件。 它可能会批量更新或推迟更新。 这使得在调用 setState() 之后立即读取 this.state 成为一个潜在的陷阱。 相反,请使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),这两者都保证在应用更新后触发
因此,您可以像这样将控制台日志放入回调中:
this.setState({ flipResult: "heads", coinURL: "heads" }, () => {
console.log("flipResult is " + this.state.flipResult);
});
问题是你不理解setState
是一个异步事件,因此你不能相信调用console.log(this.state.SOMETHING)
会给你新的状态。
函数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);
}
因此在设置状态后,它将调用您的函数,您将能够看到新状态。
注意:请注意,当您第一次单击时它显示为空,第二次单击时它将显示以前的状态,这是因为正如我所解释的,它显示的是未设置的值。
您发布的整个代码如下:
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;
由于更新状态是一个异步过程,因此我们可以使父函数异步并通过await
命令等待更新状态
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.