Skip to content

Instantly share code, notes, and snippets.

@jonidelv
Last active January 28, 2019 10:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonidelv/8ea56310619943d91fa3e6d075776d38 to your computer and use it in GitHub Desktop.
Save jonidelv/8ea56310619943d91fa3e6d075776d38 to your computer and use it in GitHub Desktop.

React performance considerations

These are some considerations to take into account when developing an application with React and Redux.

One of the most common performance failures in React is the unnecessary rendering of components. A library that can be very useful to detect this is why-did-you-update. Notifies you in the console when potentially unnecessary re-renders occur, super helpful for easy perf gains.

Another handy tool to measure performance is react-addons-perf.

Also remember to use shouldComponentUpdate() method in statefull components to check that the props of a component didn’t change and skip rendering (React by default render the component). We can use PureComponent instead of Component. This would compare all props using strict equality (===) and rerender only if any of the props change. If you want to achieve the same behavior but in a functional component I recommend you use recompose. Specifically the pure HOC. You can find how to use it here.

If you’re using Redux then connected components are already pure. Just remember that if only one of the props change, then the connected component rerenders — this includes all its children, too. So even if you use Redux for page components, you should use pure or shouldUpdate for components further down in the render tree. Also, beware that Redux does the props comparison using strict equality. Since Redux connects the state to a component’s props, if you mutate an object in the state, Redux props comparison will miss it. That’s why you must use immutability in your reducers.

To prevent useless renders in (Redux) connected components, you must also make sure that the mapStateToProps function doesn’t return new objects each time it is called. Reselect solves this problem by using memoization. Instead of computing the props directly in mapStateToProps, you use a selector from reselect, which returns the same output if the input didn’t change.

JSX

Take care of Object Literals

import React from 'react';
import MyTableComponent from './MyTableComponent';
const Datagrid = (props) => (
    <MyTableComponent style={{ marginTop: 10 }}>
        ...
    </MyTableComponent>
)

The style prop of the <MyTableComponent> component gets a new value every time the <Datagrid> component is rendered. So even if <MyTableComponent> is pure, it will be rendered every time <Datagrid> is rendered. In fact, each time you pass an object literal as prop to a child component, you break purity. The solution is simple:

import React from 'react';
import MyTableComponent from './MyTableComponent';
const tableStyle = { marginTop: 10 };
const Datagrid = (props) => (
    <MyTableComponent style={tableStyle}>
        ...
    </MyTableComponent>
)

Functions

// NEVER do this
render() {
  return <MyInput onChange={this.props.update.bind(this)} />;
}
// NEVER do this
render() {
  return <MyInput onChange={() => this.props.update()} />;
}
// Instead do this
onChange() {
    this.props.doUpdate()
}
render() {
  return <MyInput onChange={this.onChange}/>;
}

Arrays

// NEVER do this, if there are no items, SubComponent will render every time!
render() {
    return <SubComponent items={this.props.items || []}/>
}
// This will avoid re-rendering
const EMPTY_ARRAY = []
render() {
    return <SubComponent items={this.props.items || EMPTY_ARRAY}/>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment