The Great Blog

Avoid Unnecessary Rendering for Function Components in React

August 02, 2019

With the introduction of the React hooks, we are using function components more, and what you might have noticed that they render all the time, not caring if the props stay the same. For example, if you have a big list of to-do items, and you are adding a new item to the list, all the item components will re-render, even if they return the same result given the same props. Class components have additional methods to prevent unnecessary rendering: PureComponent and shouldComponentUpdate. The former one is easy to use; the user doesn’t need to write any additional logic; the component shallowly checks the props and rerenders if it detects new ones. The latter method is of the lifecycle, and the user needs to write the logic by manually comparing the properties or state, and tell the components if it has to render. Function components have a method to avoid unnecessary rendering too, and only the syntax differs a little bit. React.memo() - does component memoization, cashing result and reuse it if the props did not change.

React.memo()

A higher-order component that will memoize your component, very similar to PureComponent. It will shallowly compare current and new props of the component, and if nothing changes, React will skip the rendering of that component. To help method be effective as possible, make the prop structure as primitive values or simple objects. If you have a complex object, the comparison might fail, the component will not be memoized and will render again. The use is pretty simple:

function List() {
  return ['one', 'two'].map((item) => (
    <MemoizedListItem item={item} />
  );
}

// Memoize ListItem component
const MemoizedListItem = React.memo(function ListItem({ item }) {
  return <li>{item}</li>
})

In this case, if you add a new item to the list, only the component with the new item will render to the DOM, the first two will use the result from the last rendering.

If the prop structure is more complex and requires manual comparison, you can pass an additional function to React.memo() as a second argument. The function will receive two arguments prevProps, nextProps and it must return a boolean if the props are the same. It is the opposite return statement comparing with the shouldComponentUpdate.

const ListItem = React.memo(
  function ListItem({ item }) { ... }, // first argument
  function arePropsEqual(prevProps, nextProps) { // second argument
    return prevProps.item === nextProps.item;
  }
);

Conclusion

React.memo() is a performance optimization method, so first make sure if you need it. Do profiling of your app, measure the performance, and apply the method if it is necessary. A wrong application might lead to bugs.


Linas Spukas

Hi there! My name is Linas Spukas, I am a full stack web developer and this is my blog. About stuff and things... in development. Enjoy.