
React 15.3 was released on July 29, and the first item in release-notes was adding support for React.PureComponent, which replaces its predecessor pure-render-mixin. This article will discuss why this component is so important and where to use it.
This is one of the most significant ways to optimize react-applications, which can be implemented quite easily and quickly. Using pure-render-mixin gives a tangible increase in performance, as the number of renders in the application is reduced, and therefore react, in turn, produces much less operations.

PureComponent changes the lifecycle method shouldComponentUpdate, automatically checking if the component needs to be redrawn. At the same time, PureComponent will only render if it detects changes in the state or props of the component, which means that in many components you can change the state without having to constantly write
')
if (this.state.someVal !== computedVal) { this.setState({someVal: computedVal}) }
In the React source code, provided that the component is “Pure”, and this check is carried out:
if (this._compositeType === CompositeTypes.PureClass) { shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState); }
The use of shallowEqual indicates that a shallow params and state check occurs, so the comparison will not occur across deeply nested objects, arrays.
Deep comparison is a very expensive operation. If PureComponent caused it every time, it would do more harm than good. No one bothers to use proven shouldComponentUpdate to manually determine the need for a new render. The simplest option is direct comparison of parameters.
shouldComponentUpdate(nextProps, nextState) { return nextProps.user.id === props.user.id; }
You can also use immutable data. The comparison in this case becomes very simple, since the existing variables do not change, but new ones are always created. Libraries like Immutable.js are our sure ally.
Application features
PureComponent saves us time and allows us not to write extra code, but it is not a panacea. It is important to know the features of its use, otherwise the utility is lost. Since the PureComponent implies a shallow check, its props and state changes may remain ignored. For example, in the parent component there is a render and click handler:
handleClick() { const items = this.state.items; items.push('new-item'); this.setState({items: items}); } render() { return ( <div> <button onClick={this.handleClick} /> <ItemList items={this.state.items} /> </div> ); }
If the ItemList component is made PureComponent, then when items are changed after pressing a button, nothing will happen. This happens because this.state.items when comparing will be equal to the old version of this.state.items, although its contents have changed. However, this is easy to fix by removing mutations, for example, like this:
handleClick() { this.setState(prevState => ({ words: prevState.items.concat(['new-item']) })); }
PureComponent will always re-render components if it receives links to different objects. This means that if we do not want to lose the benefits of PureComponent, such constructions should be avoided:
<Entity values={this.props.values || []}/>
A new array, even though it is empty, will always force the component to be redrawn.
To avoid this is very simple, for example, using DefaultProps, in which you can set an initially empty state of the variable being transferred. Also very often you can see the following components:
<CustomInput onChange = {e => this.props.update (e.target.value)} />;
When creating them, a new function will always be created, which means that PureComponent will see new data every time. This is treated, for example, by bind the desired function in the component's constructor.
constructor(props) { super(props); this.update = this.update.bind(this); } update(e) { this.props.update(e.target.value); } render() { return <MyInput onChange={this.update} />; }
Also, any component that contains child elements created in JSX will always return false on shallowequal checks.
It is important to remember that PureComonent skips drawing not only the component itself, but all its “children”, so it is safest to use it in the presentational components, without “children” and without dependence on the global state of the application.
What is the result
In fact, the transition to PureComponent is quite simple, if you know a number of features related to JS rather than React. In many components I replaced:
class MyComponent extends Component {…}
on:
class MyComponent extends PureComponent {…}
... and they continued to work quietly, and with increased productivity.
So try and use, the component is very useful.
EDIT
Thanks
raveclassic for a useful note. In case the pure component has children, all child components dependent on the context change will not react to changes if the contextTypes is not declared in the parent pure component.