点击按钮时,应该通过这些函数将文本“第二条消息”和“第三条消息”添加到状态:
class Button extends React.Component {
constructor(props) {
super(props);
this.addMessage = this.addMessage.bind(this);
}
addMessage() {
this.props.addMessage('second message'); // This is ignored
this.props.addMessage('third message'); // Only this message is added
}
render() {
return(
<button onClick={this.addMessage}>Add text</button>
)
}
}
但只有其中一个在开火。
我创建了一个显示问题的简单片段。
class Button extends React.Component {
constructor(props) {
super(props);
this.addMessage = this.addMessage.bind(this);
}
addMessage() {
this.props.addMessage('second message'); // This is ignored
this.props.addMessage('third message'); // Only this message is added
}
render() {
return(
<button onClick={this.addMessage}>Add text</button>
)
}
}
class Messages extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<p>{this.props.message}</p>
)
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
messages: [{
text: 'first message'
}]
}
this.addMessage = this.addMessage.bind(this);
}
addMessage(message) {
let messages = this.state.messages.slice();
messages.push({text:message});
this.setState({messages: messages});
}
render() {
let messages = [];
this.state.messages.forEach((message) => {
messages.push(<Messages message={message.text}></Messages>);
});
return(
<div>
{messages}
<Button addMessage={this.addMessage} />
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id="root"></div>
提前致谢!
最佳答案
状态更新可能是异步的
引自reactjs docs about state updates :
React may batch multiple
setState()
calls into a single update for performance.Because
this.props
andthis.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
第二次调用 addMessage()
使用 this.state
设置新状态。但是因为 setState()
是异步的,所以我的状态还没有更新,这会导致你的第二次调用覆盖你的第一个:
addMessage(message) {
// here you access this.state which hasn't been updated yet in your second call
let messages = this.state.messages.slice();
messages.push({text: message});
this.setState({messages: messages});
}
To fix it, use a second form of
setState()
that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:
使用一个箭头函数来传递先前的状态,包括对 setState()
的先前调用的更改,以计算新状态。这将解决您的问题。
使用 es6 传播语法:
this.setState((prevState, props) => ({
messages: [...prevState.messages, {text: message}]
}));
使用 slice()
:
this.setState((prevState, props) => {
let messages = prevState.messages.slice();
messages.push({text:message});
return {messages};
});
关于javascript - 为什么多次调用 setState() 时状态不能正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44876902/