Jan Carlo Viray React · Angular · Node · Go · SQL · NoSQL · Cloud · Entrepreneurship

A year from now you’ll wish you started today — Karen Lamb

LinkedIn ·  Twitter ·  Github

React Props in State an Anti-Pattern

Passing the initial state to a component as a prop is an anti-pattern because the getInitialState method is only called the first time the component renders - and never called after that. This means that if you re-render the parent, while passing a different value as a prop, the component will not update the UI because it will keep the state from the first time it was rendered. This will make the application very prone to errors.

Solution? Make the components stateless. They are easier to test because they render an output based on an input. Have the parent component contain the passed-in data as its own state, then if the state changes, it re-renders its children, while passing in everything they need through props.

What does this look like in React?

The parent component (or so called “Controller View”) would get all of the data through an ajax call (use flux pattern) and place it in getInitialState.

Another solutions is to send in “handlers” to the children, then these parent handlers would do a setState once they are invoked by their children, therefore doing re-rendering of the UI. Here’s a good example at StackOverflow: reactjs-two-components-communicating.

Best solution is to have a “Container” or “ControllerView” passing down the handler to the children components…

var ListContainer = React.createClass({
	handleFilterUpdate(filterValue){
		this.setState({
			nameFilter: filterValue
		});
	}	,
	render(){
		return (
			<div>
				<Filters updateFilter={this.handleFilterUpdate}/>
				<List items={displayedItems}/>
			</div>
		);
	}
});

var Filters = React.createClass({
	handleFilterChange(){
		var value = this.refs.filterInput.getDOMNode().value;
		this.props.updateFilter(value);
	},
	render(){
		return (
			<div><input ... ref="filterInput" onChange={this.handleFilterChange} /></div>
		)
	}
});
// this is not good
getInitialState: function(){
	return {
		text: this.props.text
	}
}

Another problem with this is that the parent that passed the text property might be expecting that it contains the latest value, but it does not.

Using props, passed down from parent to generate state in getInitialState often leads to duplication of “source of truth”, which is where the real data is.

If you have any questions or comments, please post them below. If you liked this post, you can share it with your followers or follow me on Twitter!