Make React Fast Again [Part 2]: why-did-you-update

Written by edelstein | Published 2017/06/09
Tech Story Tags: react | make-react-fast-again | facebook-react | web-development | react-performance

TLDRvia the TL;DR App

React is usually pretty fast, but it’s easy to make small mistakes that lead to performance issues. Slow component mounts, deep component trees, and unnecessary render cycles can quickly add up to an app that feels slow.

Luckily there are lots of tools, some even built in to React, that help with diagnosing performance issues. In this series we’ll highlight tools and techniques for making React apps fast. Each post will also have an interactive, and (hopefully) fun demo!

The Problem: Unnecessary Render Cycles

One of the most common issues that affects performance in React is unnecessary render cycles. By default, React components will re-render whenever their parent renders, even if their props didn’t change.

For example, if I have a simple component like this:

class DumbComponent extends Component {render() {return <div> {this.props.value} </div>;}}

With a parent component like this:

class Parent extends Component {render() {return <div><DumbComponent value={3} /></div>;}}

Whenever the parent component renders, DumbComponent will re-render, despite its props not changing.

Generally, if render runs, and there were no changes to the virtual DOM, it is a wasted render cycle since the render method should be pure and not have any side effects. In a large-scale React app, it can be tricky to detect places where this happens, but luckily, there’s a tool that can help!

Why did you update?

why-did-you-update is a library that hooks into React and detects potentially unnecessary component renders. It detects when a component’s render method is called despite its props not having changed.

Setup

  1. Install with npm: npm i --save-dev why-did-you-update
  2. Add this snippet anywhere in your app:

import React from 'react'

if (process.env.NODE_ENV !== 'production') {const {whyDidYouUpdate} = require('why-did-you-update')whyDidYouUpdate(React)}

Note that this tool is great in local development but make sure it’s disabled in production since it will slow down your app.

Understanding the output

why-did-you-update monitors your app as it runs and logs components that may have changed unnecessarily. It lets you see the props before and after a render cycle it determined may have been unnecessary.

Fixing unnecessary renders

Once you’ve identified components in your app that are re-rendering unnecessarily, there are a few easy fixes.

Use PureComponent

In the above example, DumbComponent is a pure function of its props. That is, the component only needs to re-render when its props change. React has a special type of component built-in called PureComponent that is meant for exactly this use case.

Instead of inheriting from React.Component, use React.PureComponent like this:

class DumbComponent extends PureComponent {render() {return <div> {this.props.value} </div>;}}

Then, the component will only re-render when its props actually change. That’s it!

Note that PureComponent does a shallow comparison of props, so if you use complex data structures, it may miss some prop changes and not update your components.

Implement shouldComponentUpdate

shouldComponentUpdate is a component method called before render when either props or state has changed. If shouldComponentUpdate returns true, render will be called, if it returns false, nothing happens.

By implementing this method, you can instruct React to avoid re-rendering a given component if its props don’t change.

For example, we could implement shouldComponentUpdate in our dumb component from above like this:

class DumbComponent extends Component {shouldComponentUpdate(nextProps) {if (this.props.value !== nextProps.value) {return true;} else {return false;}}

render() {return <div>foo</div>;}}

Demo!

To demonstrate why-did-you-update, I installed the library in the TodoMVC app on Code Sandbox, an online React playground. Open the browser console and add some TODOs to see the output.

https://codesandbox.io/s/xGJP4QExn

Notice that a few components in the app are rendering unnecessarily. Try implementing the techniques described above to prevent unnecessary renders. If done correctly, there should be no output from why-did-you-update in the console.

Debugging Performance Issues in Production

why-did-you-update only works in local development. If you’re interested in understanding performance issues in your production app, try LogRocket.

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong.

LogRocket instruments your app to record performance timings, Redux actions/state, logs, errors, network requests/responses with headers + bodies, and browser metadata. It also records the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

LogRocket | Logging and Session Replay for JavaScript Apps_LogRocket helps you understand problems affecting your users, so that you can get back to building great software._logrocket.com

Conclusion

why-did-you-update is a handy tool for detecting potentially unnecessary component re-renders, helping you make your app perform better.

Since why-did-you-update only works in development, check out LogRocket, for diagnosing bugs and performance issues in production.

For more React performance tips, check out parts 1 and 3 of this series:

Make React Fast Again [Part 1]: Performance Timeline_React is usually pretty fast, but it’s easy to make small mistakes that lead to performance issues. Slow component…_blog.logrocket.com

Make React Fast Again [Part 3]: Highlighting Component Updates_React is usually pretty fast, but it’s easy to make small mistakes that lead to performance issues. Slow component…_blog.logrocket.com

It’s tough to keep up-to-date on front-end dev. Join our weekly mailing list to learn about new tools, libraries and best practices that will help you build better apps:


Published by HackerNoon on 2017/06/09