Chopta, UttaraKhand

Save wasted renders using React.memo

--

In mobile friendly app development performance of App really matters. Any one extra render can affect the performance of our application.

Before getting into the solution first lets understand how react renders the changes and what causes the wasted render.

React re-renders the UI whenever state associated with any component changes. And if this state is passed as a prop to components, then each component receiving this state as a prop will rendered. This is the how react should work right? So where is the issue? The issue is in JS referential equallity. In Javascript objects are of non-primitive types. Which means they work on references. Whenever we pass, assign or compare objects, then we are not comparing the values instead we are comparing the references. To make it more clear {}==={} is false in javascript. Here we are comparing two memory addresses not the value. Read more about it.

In React when we deal with objects we have to be extra attentive about using them in state and props.

Lets understanding this by an example.
To visualize extra render we can use ReactDevTools . To enable visualization of render we have to turn on this feature. To do so Navigate to React Dev Tools and check the box which says Highlight updates when components render. Make sure it is checked. If you don’t have react-dev-tools download it from here.

Consider following presentation-al component. It receives an object pet as a prop and displays the data in UI.

This DumbComponent is used by App component to render pet info. In App component there is a button on click of which we are assigning same information to an object.

Although, we are passing same information on click of button, even though both of the App and DumbComponent will be rendered. The Green lines are showing re-rendering.

Without React.memo()/PureComponent

In class component we have PureComponent which only re-renders the class component when there is a difference in shallow comparison of Props and state. Which in turn increases the performance of React app by saving few renders. But unfortunately it only work with Class Components .

For functional component we have React.memo(). It is a hoc which takes the component as parameter and returns the memoized version of it. React.memo() uses memoization in functional component in order to prevent extra render by proving referential equality.

React.memo() was introduced in 16.6 , so make sure you are using React v16.6 or later.

If we make our DumbComponent memoized then we can save this extra rendering. Lets change export default DumbComponent line to export default React.memo(DumbComponent); and run our applicaiton.

with React.memo(DumbComponent)

We can see our DumbComponent is now not rendering on every click. But our App component is still re-rendering every time we click on button. Lets fix this as well by adding React.memo() to App component.

with React.memo(App) and React.memo(DumbComponent)

Now we have prevented the extra re-rendering. We can that even though after multiple clicks on button as passing same object is not triggering the re-rendering.

Note: React.memo() do a shallow comparison of objects.

If we pass nested objects having same data then there will be extra re-render because React.memo() does only shallow comparison not the deep comparison.
We can resolve this by passing out own comparison handler to React.memo().

Custom Handler

propsAreEqualfunction must return true if prevProps and nextProps are equal.

You may use React.memo() for all Presentational Components, but the component which are going to render for every prop change does not need React.memo() . As by using React.memo() we are forcing react to perform one more additional check on passed props .

Here is the sample code containing example for React.memo() . https://github.com/rahuulmiishra/reactmemo

--

--