想象一下这段代码:
class App extends React.Component {
state = {
name: "george",
counter: 1
};
onClick() {
this.setState({
counter: 123,
name: this.state.name + this.state.counter
});
}
render() {
return (
<div
className="App"
onClick={() => {
this.onClick();
}}
>
<h1>Hello CodeSandbox</h1>
<h2>{this.state.name}</h2>
<h2>{this.state.counter}</h2>
</div>
);
}
}
如果我单击div
,输出是:
george1
123
您可以看到,state.name
的值是george1
,包含了的值,该值在 onClick
称为时是当前的。不过,state.counter
值本身具有新的值。
这是怎么解释的?因为如果我这样做:
onClick() {
this.setState({
counter: 123
});
setTimeout(() => {
this.setState({
name: this.state.name + this.state.counter
});
}, 1000);
}
现在输出是
george123
123
它基本上是相同的代码,但具有不同的时间。那么,是什么解释了这种行为呢?为什么在第一种情况下,它具有嵌入在this.state.counter
this.state.name
**?**中的(单击时)的当前值,而在第二种情况下则没有?
演示。
我知道,如果我想将counter
的旧值嵌入到this.state.name
中,并更新this.state.counter
,我也可以这样做:
onClick() {
this.setState({ // even safer to use functional setState here
name: this.state.name + this.state.counter
}, ()=>{
this.setState({ // and here
counter:123
})
});
}
它比No1方法安全吗(结果相同)?
发布于 2019-09-17 14:48:39
在这两个示例中都使用了counter
的值。区别在于当counter
的值发生变化时。在本例中:
onClick() {
this.setState({
counter: 123,
name: this.state.name + this.state.counter
});
名称是george1
,因为this.state.counter
仍然被设置为1
(它还没有更新)。
在本例中:
this.setState({
counter: 123
});
setTimeout(() => {
this.setState({
name: this.state.name + this.state.counter
});
}, 1000);
您首先要更新counter
的值,所以在超时this.state.counter
引用新值之后,name
值将是george123
。
另外,如果需要在setState
函数中引用状态,则应该使用回调,以保证状态的正确值。
发布于 2019-09-17 15:11:10
正如您在注释和答案中所看到的,使用setTimeout
并不那么可靠。大多数时候,你可以改变你的逻辑,解决你的问题。我不太确定您的应用程序中的计数器将如何变化,但是下面是一个如何管理它的示例。使用setState
回调,您可以同时达到相同的counter
和name
值。
class App extends React.Component {
state = {
name: "george",
counter: 1
};
onClick() {
this.setState(prevState => ({
counter: prevState.counter + 1,
name: `${prevState.name}${prevState.counter + 1}`
}));
}
render() {
return (
<div onClick={() => this.onClick()}>
<h2>{this.state.name}</h2>
<h2>{this.state.counter}</h2>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
https://stackoverflow.com/questions/57976686
复制相似问题