React State

Last time we looked at how to use properties, to affect the initial rendering of components. Today we’ll take a look at how to use state, how it differs from properties and some things you should consider when using state.

Like properties, state affects how a component behaves and renders. Unlike properties, there’s no way to define what state should be applied to components via JSX…

You can find the accompanying source-code, for this tutorial, at: https://github.com/formativ/tutorial-react-state.
Please post any errors you find, or questions you have as comments on this article or as issues on GitHub.
Thanks to Pete Hunt, Ben Alpert and Christopher Chedeau for helping to improve this!

Properties vs. State

Properties are defined when components are created, whether by JSX or by pure JavaScript. State, on the other hand, is only seen on the inside of component definitions. This is the first, and most important difference between the two.

When you think of properties, you should be thinking of component initialisation. When you think of state, you should think of an internal data-set which affects the rendering of components.

There are ways to validate the presence and type of properties, but there is no such mechanism for state. You, as the developer of a component, are the only person who should know what state your component needs, and the correct data types which should be accepted/provided.

State should be considered private data.

Setting Initial State

Before we can use state, we need to declare a default set of values for the initial state. This is done by defining a method called getInitialState() and returning an object:

/**
* @jsx React.DOM
*/

var InterfaceComponent = React.createClass({
getInitialState : function() {
return {
name : "chris",
job : "developer"
};
},
render : function() {
return <div>
My name is {this.state.name}
and I am a {this.state.job}.
</div>;
}
});

React.renderComponent(
<InterfaceComponent />,
document.body
);

This method tells the component which values should be available from the first render cycle, until the state values are changed. You should never try to use state values without first declaring them in this manner.

Setting State

Setting state should only be done from inside the component. As mentioned, state should be treated as private data, but there are times when you may need to update it. This is how that is done:

/**
* @jsx React.DOM
*/

var InterfaceComponent = React.createClass({
getInitialState : function() {
return {
name : "chris"
};
},
handleClick : function() {
this.setState({
name : "bob"
});
},
render : function() {
return <div onClick={this.handleClick}>
hello {this.state.name}
</div>;
}
});

React.renderComponent(
<InterfaceComponent />,
document.body
);

You cannot set new state values until the component has been mounted. This happens when it’s passed (whether directly or by nesting it) to the React.renderComponent() method. Then again, why would you need to?

Setting state in this way is only really needed when your component’s rendering and behaviour depends on outside factors. We’ll look at examples of that later on in the series.

Replacing State

It’s also possible to replace values in the state by using the replaceState() method. Let’s look at an example of this:

/**
* @jsx React.DOM
*/

var InterfaceComponent = React.createClass({
getInitialState : function() {
return {
first : "chris",
last : "pitt"
};
},
handleClick : function() {
this.replaceState({
first : "bob"
});
},
render : function() {
return <div onClick={this.handleClick}>
hello { this.state.first + " " + this.state.last }
</div>;
}
});

The replaceState() method is for when you want to clear out the values already in state, and add new ones.

Avoiding State

The use of state should be as limited as it can get. When you use state, you run the risk of introducing a number of (sometimes subtle) errors in the behaviour and rendering of your components.

If you decide to use properties to define your initial state; your properties might change, leaving your initial state calculations based on stale data. You also introduce tight coupling between the properties that need to be defined, and the internal state of the component.

A general rule is not to use state for static components. If you component does not need to change, based on external factors, then do not use state. It’s better to calculate rendered values in the render() method.

You can learn more about the correct use of state at: http://facebook.github.io/
react/blog/2013/11/05/thinking-in-react.html
.

Conclusion

State is a double-edged sword. On the one hand, it’s useful for sanely controlling internal data. On the other, it can lead to all sorts of mayhem, if not properly controlled. Use it wisely!

If you’re unsure of whether or not you should be using state, get onto IRC and ask! You can usually find someone there, at all hours, who will be willing to help. You can find us on #reactjs (Freenode).

If you enjoyed this tutorial; it would be helpful if you could click the Recommend button and share it with other developers.