DEV Community

Cover image for React memo
abhmohan
abhmohan

Posted on

React memo

Hello Guys...

In this post I will explain how we can make use of React memo to improve the UI performance.

Prerequisite

Before you dive into the article, it is important you understand what react hooks are. It is also important to understand how a HOC(Higher Order Component) works. If you are new to these concepts, I will suggest you to go through the official documentation.
Here is the link to hooks (hooks).

Here is the link to HOC (HOC).

When we build an application, it is important we consider different ways of improving the performance because every second or even every millisecond matters for the user.

Once of the ways to improve UI performance is by avoiding unnecessary rendering. Wrapping a component with memo helps us avoid unnecessary rendering. React memo basically gives a memoized version of the component. When I say avoid unnecessary rendering I mean not rendering a component when it's props have not changed.

Let us see an example.

  import MyComponent from './MyComponent';

  const MyApp = () => {
    const [incrementValue, setIncrementValue] = useState(0);
    const [decrementValue, setDecrementValue] = useState(0);

    const handleIncrement= () => {
      setIncrementValue(incrementValue + 1);
    }

    const handleDecrement = () => {
      setDecrementValue(decrementValue + 1);
    }
    return (
      <div>
        <button onClick={handleIncrement}>Increment</button>
        <button onClick={handleDecrement}>Decrement</button>
        // 1st MyComponent
        <MyComponent key='1' value={`Increment-${incrementValue}`} />
        // 2nd MyComponent
        <MyComponent key='2' value={`Decrement-${decrementValue}`} />
      </div>
    )
  }

  // MyComponent.js
  const MyComponent = ({ value }) => {
    console.log('I am being rendered', value);
    return (
      <p>Value is {value}</p>
    )
  }

  export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

Above I have a component MyApp which renders couple of buttons. The first button increases the incrementValue and the second one decreases the decrementValue. Also I have couple of MyComponent components.

Let's try to understand what MyComponent is doing here.

MyComponent takes a value prop and displays the value. I have added a console statement to clearly understand which component is getting rendered.

Now when I load MyApp component, you will see

  I am being rendered Increment-0    //1st MyComponent
  I am being rendered Decrement-0    //2nd MyComponent
Enter fullscreen mode Exit fullscreen mode

in the console because the App was rendered for the first time. Fair enough.

Now I click on Increment button. What do you this should be logged in the console.

  I am being rendered Increment-1   //1st MyComponent
  I am being rendered Decrement-0   //2nd MyComponent
Enter fullscreen mode Exit fullscreen mode

This means both the MyComponent were re-rendered. If you look closely at the 2nd MyComponent, the prop value did not change because nothing happened to decrementValue when we clicked the Increment button. It is still the same(0) but was re-rendered. So this is an unnecessary render. How do we avoid re-rendering of 2nd MyComponent?

Let's make a small change in the MyComponent.js

  import { memo } from 'react;
  const MyComponent = ({ value }) => {
    console.log('I am being rendered', value);
    return (
      <p>Value is {value}</p>
    )
  }

  export default memo(MyComponent);
Enter fullscreen mode Exit fullscreen mode

Now when we reload MyApp, for the initial rendering we will still see

  I am being rendered Increment-0    //1st MyComponent
  I am being rendered Decrement-0    //2nd MyComponent
Enter fullscreen mode Exit fullscreen mode

in the console.

Now I click the Increment button. What do you think will be logged to console!!!

  I am being rendered Increment-1    //1st MyComponent
Enter fullscreen mode Exit fullscreen mode

This means only 1st MyComponent was rerendered because its *value * prop changed but for the 2nd MyComponent nothing changed, so it didn't re-render.

So we saw how React memo helps in avoiding unnecessary rendering thus improving the UI performance.

This is a very simple example where I demonstrated how react memo
helps us in avoiding unnecessary rendering. But we have to understand when should a component be wrapped with memo because memoizing something comes with a cost.

Usually,
1. if a component is light weight and renders with different
props, you may not want to memoize it.
2. if a component is heavy and it renders with same props,
you would like to memoize it.

Note - This is a simple example where the component accepts a simple string prop. We can all also have a function as a prop and for a function prop we can memoize it with using useCallback hook to avoid unnecessary rendering.

Conclusion

React memo is one of the ways to improve the UI performance. It might not that relevant when the application is small, but as the application grows, it becomes very important to check for different ways to improve the performance of the application.

Top comments (0)