State. One of the most complicated concepts in React.js nomenclature. While some of us already got rid of it in our projects (Redux anyone?) by externalizing state, it is still widely used feature of React.js.
While convenient, it can cause some issues. Robert Pankowecki, one of Rails meets React.js authors had the problem with validations when he started his journey with React.
The story went like this: Validations seem to be quite easy to do, but there is a problem of vanilla form - first time user sees the input it should not get validated, even if it’s invalid to have this input empty. This is definitely a stateful behaviour - so Robert concluded it’ll be good to put his validation messages in state.
So basically he just went and implemented the logic like this:
// ...
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value });
this.validateTitle();
},
validateTitle: function validateTitle () {
if(this.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
// ...
Bam. This code doesn’t work. Why is so? This is because setState works in an asynchronous way. That means after calling setState the this.state variable is not immediately changed. This is described in docs under “Notes” section:
setState() does not immediately mutate this.state but creates
a pending state transition.
Accessing this.state after calling this method can potentially
return the existing value.
So it is rather a misunderstanding or lack of knowledge than something really weird. Robert could avoid his problem by reading the docs. But you can agree that it’s a rather easy mistake to make for a beginner!
This situation has triggered some interesting discussions internally in the team. What can you expect from setState? What guarantees you have? Why can you be sure that state will get updated correctly if you change the input and press “Submit” immediately? To understand what’s going on and to make an interesting journey into React internals I’ve decided to trace what happens under the hood if you call setState. But first, let’s solve the problem Robert had in an appropriate way.
continue reading →