Performance Issues

The issue

React massively optimizes Context under the hood to avoid unnecessary re-renders of components or avoid lengthy component hierarchies. Comparing the old value of the Context Provider with the new one, Consumer components are only re-rendered if the value in the Context Provider has changed.

While this may sound, it creates a minor issue that we need to look out for in our React app. Using it within the render() method concerns the Context Provider whose value is recreated on the fly if we use it within the render() method. Creating the Context value outside of the render() method is recommended and passing a reference to the value instead of a newly created value.

Example problem

Here is an example which you should NOT recreate:

class App extends React.Component {
    state = {
        color: 'red',
    };

    render() {
        return (
            <Provider value={{ color: this.state.color }}>
                <MoreComponents />
            </Provider>
        );
    }
}

We are creating a new object {color: this.state.color} with each call of the render() method. All Consumer components would re-render because React only checks if the reference of the value in the current render() is the same as the reference in the previous render() call, which is never the case as a new object is created on the fly each time.

Example solution

However, we can transform the above example to avoid this situation and make sure that React’s performance algorithm can get to work:

class App extends React.Component {
    state = {
        color: 'red',
    };

    render() {
        return (
            <Provider value={this.state}>
                <MoreComponents />
            </Provider>
        );
    }
}

In this example, we merely pass a reference to the state object of the component. Since this remains intact during component re-rendering, it does not trigger a re-render if the content of the state does not change.

Get hands-on with 1200+ tech skills courses.