Reputation: 4658
I have a method submitMessage
that is supposed to concatenate the current message that has been stored in my input state and then clear it:
submitMessage() {
this.setState({
input: '',
messages : [...this.state.messages, this.state.input]
});
}
The method is working as intended and the whole app too, what I don't understand is why input can be cleared before the concatenate, is input and this.state.input
not in the same place in memory ?
Here is my full code:
class DisplayMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
messages: []
}
}
handleChange(event) {
this.setState({
input: event.target.value,
messages: this.state.messages
})
}
submitMessage() {
this.setState({
input: '',
messages : [...this.state.messages, this.state.input]
})
}
render() {
return (
<div>
<h2>Type in a new Message:</h2>
<input onChange={this.handleChange.bind(this)} value={this.state.input} />
<button onClick={this.submitMessage.bind(this)}>Submit</button>
<ul>{this.state.messages.map((item) => {
return <li key={item + 1}>{item}</li>
})}
</ul>
</div>
);
}
};
Upvotes: 0
Views: 269
Reputation: 202618
Why are
<input />
andthis.state.input
not in the same place in memory?
input
is an html DOM element, while the other, this.state.input
is a javascript object, they are two completely different things. The only thing relating the two is the JSX syntax and react framework.
Why can input be cleared before the message concatenation?
In react, state and props are treated as immutable objects, and react state works between render cycles. All state updates within any single cycle are queued up and batch processed for the next render cycle. Setting this.state.input
to an empty string and appending it to the this.state.messages
array are queued to to be processed for the next rendered view.
The following are all equivalent in terms of next computed state:
this.setState({
input: '',
messages: [...this.state.messages, this.state.input],
});
and
this.setState({
messages: [...this.state.messages, this.state.input],
input: '',
});
and
this.setState({ input: '' });
this.setState({
messages: [...this.state.messages, this.state.input],
});
and even
this.setState({ input: '' });
this.setState({
messages: [...this.state.messages, this.state.input],
});
this.setState({
messages: [...this.state.messages, this.state.input],
});
The last one you may find surprising (what!?), but recall that state state is immutable and batch processed, so in the case of updating messages
, this.state.messages
and this.state.input
have the same values in both calls, and thus, the last one invoked is what sets state. BTW, (and outside the scope of this question), functional state updates help solve the issue with this last example.
Upvotes: 1