When a component needs to keep track of information between renderings the component itself can create, update, and use state. We’ll be working with a fairly simple component to see state working in action. We’ve got a button that keeps track of how many times you’ve clicked it.
Here’s the code:
class Button extends React.Component {
constructor() {
super();
this.state = {
count: 0,
};
}
updateCount() {
this.setState((prevState, props) => {
return { count: prevState.count + 1 }
});
}
render() {
return (<button
onClick={() => this.updateCount()}
>
Clicked {this.state.count} times
</button>);
}
}
So now we’re working with state things are a bit more complicated. But we’ll break it down to make it more understandable.
Our first real difference between props and state is, state is created in the component. Let’s look at the constructor method:
constructor() {
super();
this.state = {
count: 0,
};
}
This is where state gets it’s initial data. The inital data can be hard coded (as above), but it can also come from props. Well that’s just confusing. It is, I know. But it makes sense – you can’t change props, but it’s pretty reasonable to want to do stuff to the data that a component receives. That’s where state comes in. Moving on brings us to our second difference, state is changeable
Here’s updateCount again:
updateCount() {
this.setState((prevState, props) => {
return { count: prevState.count + 1 }
});
}
We change the state to keep track of the total number of clicks. The important bit is setState. First off, notice that setState takes a function, that’s becuase setState can run asynchronously. It needs to take a callback function rather than updating the state directly. You can see we have access to prevState within the callback, this will contain the previous state, even if the state has already been updated somewhere else. Pretty slick, huh?
But React goes one step better, setState updates the state object and re-renders the component automagically. Yeah, this is pretty great of React to do, no need for us to explicitly re-render or worry about anything. React will take care of it all!
It is tempting to write this.state.count = this.state.count + 1. Do not do this! React cannot listen to the state getting updated in this way, so your component will not re-render. Always use setState. It might also be tempting to write something like this:
// DO NOT USE
this.setState({
count: this.state.count + 1
});
Although this might look reasonable, doesn’t throw errors, and you might find examples that use this syntax online, it is wrong. This does not take into account the asychronous nature that setState can use and might cause errors with out of sync state data.