Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

react
communitycreator

React faster performance: highlighting React Components updates

Chidume Nnamdi

A problem we commonly face when using React is that of wasted renders. To conquer this problem, we need sophisticated tools that examine these problems to see why and how they occur – React Developer Tools provide just that.

In this shot, we will explore how we can leverage React Developer Tools to yet another good cause. But first, we have to know what a wasted render is.

Wasted renders

A wasted render occurs when a component is re-rendered for no apparent reason.

Why is that?

All Components in React have an internal state and properties called props that they maintain. Now, when either of these changes, common sense tells us that the Component(s) should be re-rendered so the new states and props will reflect in the DOM.

If none of the state and props values have been changed, common sense also tells us that there is no need to re-render the component since neither the state nor the props values have changed.

Now, when a Component is rendered when the state and the props have not changed, this is wasteful rendering. Our app might suffer from performance slowdowns.

This will be inconsequential when the Component sub-tree is about five to ten components. However, when looking at the sub-tree on the scale of hundreds or thousands of components, the performance slowdown will be very apparent.

See this example:

class Count extends Component {
    constructor() {
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <div>Count: {this.state.count}</div>
                <button onClick={() => this.setState({count: this.state.count + 1})}>Incr</button>
                <button onClick={() => this.setState({count: this.state.count})}>No Incr</button>
            </div>
        )
    }
}

We have a Component that manages a local count state. We have two buttons, Incr and No Incr, each of which has a click handler functionthis function updates the state count using the setState method.

Component rendering is mainly caused by the setState method.

The Incr button increases the count state by one and No Incr sets the state to the current state value. However, either one would cause a re-rendering when clicked on in the Count component. Incr actually increases the count state, so the Component should re-render to display the new count state.

No Incr does not change the count state, and yet the Component is re-rendered. On the initial rendering, the count state is zero when on No Incr. If clicked, the state is set to itself, which is zero, and the component will re-render. Because the previous count state was zero, and the current count state is zero, so there should be no need for the component to re-render.

To verify this, let’s add a log message on the componentDidUpdate and componentWillUpdate lifecycle hook:

class Count extends Component {
    constructor() {
        this.state = {
            count: 0
        }
    }
    componentWillUpdate(nextProps, nextState){
        console.log('componentWillUpdate')
    }
    
    componentDidUpdate(prevProps, prevState) {
        console.log('componentDidUpdate')
    }
    render() {
        return (
            <div>
                <div>Count: {this.state.count}</div>
                <button onClick={() => this.setState({count: this.state.count + 1})}>Incr</button>
                <button onClick={() => this.setState({count: this.state.count})}>No Incr</button>
            </div>
        )
    }
}

This will help us know when the component is updated.

Now open the Console on DevTools. Click on the No Incr button twice. We will see two logs on our console:

componentWillUpdate componentDidUpdate

That verifies that No Incr triggers unnecessary re-renders, or wasted renders.

Highlighting rendering components

React Developer Tools is a DevTool extension that helps us debug, profile, and monitor our React app execution in our browser. It provides us with a highlighter that colors React component(s) boundaries whenever they are re-rendered.

We might not have the chance to add logs in componentDidUpdate and componentWillUpdate lifecycle methods of every component in our project to detect when an unnecessary render occurs.

React Developer Tools has a feature that can help us visualize components re-renders/updates.

Install the React Developer Tools extension here.

Now, whenever you load a React app, a React tab will appear on the DevTool:

Click on the React tab. You will see a checkbox with the label “Highlight updates.” If you don’t see one, click on the settings icon, a modal will pop up, and there you will see a “Highlight updates” checkbox. If it is not checked, click on it to check.

Now, when a component updates, the boundaries of the component will be highlighted with a color.

There are different colors the React Dev Tool can show: blue, green, yellow, and red. They depend on the frequency of the components update. If a component is frequently updated, a red color highlight will be shown.

  • Blue: infrequent updates
  • Green: not too infrequent
  • Yellow: frequent
  • Red: very frequent

Let’s see a demo:

class Count extends Component {
    render() {
        return (
            <div className="count">Count: {this.props.count}</div>
        )
    }
}
class Counter extends Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div className="counter">
                <Count count={this.state.count} />
                <button onClick={() => this.setState({count: this.state.count + 1})}>Incr</button>
                <button onClick={() => this.setState({count: this.state.count})}>No Incr</button>
            </div>
        )
    }
}
class App extends React.Component {
    render() {
        return ( 
            <Counter />
        )
    }
}
export default App

This is still the same as our previous example, it’s just that we re-factored it. A Component deals with displaying the count state, except it all is still the same.

Now, run npm run starts to serve the app. Then go to localhost:3000 to load the app in your browser.

Make sure the “Highlight Updates” box is ticked.

Click on the Incr button, and we see a blue color appear around the Counter and Count components.

This shows that the Counter and Count components are updated.

Click on the No Incr button; the blue color highlights the Counter and Count components. These show that both Counter and Count are updating.

Now, let’s memoize our Counter component to only update when the state and props have changed:

class Count extends React.PureComponent {
    render() {
        return (
            <div className="count">Count: {this.props.count}</div>
        )
    }
}
class Counter extends React.PureComponent {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div className="counter">
                <Count count={this.state.count} />
                <button onClick={() => this.setState({count: this.state.count + 1})}>Incr</button>
                <button onClick={() => this.setState({count: this.state.count})}>No Incr</button>
            </div>
        )
    }
}
class App extends React.Component {
    render() {
        return ( 
                <Counter />
                )
    }
}
export default App

We memoized Counter and Count by making them extend the React.PureComponent. This feature makes the React Components only re-render when the state and props value changes.

When we click on the Incr button, it will display a blue highlight on the Counter and Count because the state value is changed every time it is clicked.

Now, click on the No Incr button. There will be no color highlight appearing at all. This shows that no component was re-rendered/updated, which is good because there is no need for this, as no state or props were changed.

Regarding the color types, notice that the color highlights we saw above are all blue. This is because of how infrequently we press the buttons to re-render the components.

Now, click on the Incr button rapidly and increase it gradually; you will see the color highlight change from blue to green to yellow and finally red.

This tool helps us easily identify in which part of our app re-rendering is happening.

Conclusion

This is another tool for your belt.

If you have any questions regarding this or anything I should add, correct or remove, feel free to comment, email, or DM me.

RELATED TAGS

react
communitycreator

CONTRIBUTOR

Chidume Nnamdi
Copyright ©2022 Educative, Inc. All rights reserved
RELATED COURSES

View all Courses

Keep Exploring