React Memo

Learn via video courses

Overview

In software development, we're typically focused on performance improvements and ways to speed up our products so that users have a better experience. Users like rapid and quick user interfaces (UI). Users consider UI reaction delays of less than 100 milliseconds as being quick, whereas delays of between 100 and 300 milliseconds are already noticeable. You can achieve lightning-fast React app performance in a variety of methods using native features and third-party solutions. React provides a higher-order component called React.memo() that avoids redundant renderings.

Introduction

By using an optimization approach called memoization, we may save the most recent value or object that was produced by a resource-intensive function. When the function is called again with the same arguments, it enables us to avoid expensive computations.

Memoization is utilized in React to optimize app performance. It can be used to eliminate unnecessary renderings of components involved in the component hierarchy and by storing the return value of callbacks in the cache and values of costly utility methods.

React is based on the concept of rendering components in the virtual DOM before updating the browser's actual Document Object Model. This results in a lot of memory and processing time being lost on pointless renderings caused by unaccounted-for state changes. An application can make greater use of its computational resources by using memoization in the proper way.

However, abusing it could prevent us from enjoying its benefits. Furthermore, wasteful memoization occasionally costs more than ignoring it, which hurts the application's speed.

What is React Memo?

The React.memo is a function that you can use to enhance the render efficiency of hooks and pure function components. It was first made available in React v16.6. The memo comes from the word memorization. In other words, if a function wrapped in React.memo is invoked again with the same input, it will return the cached version of the result. Because it is only used for pure functions, if the parameters don't change, neither does the outcome. In those cases, React.memo prevents the execution of functions.

The following points describe some features of React.memo() :

  • It is a higher order component: it is a function that receives a component and then produces another component.
  • When you know in advance that a component will return the same output to the DOM: when given the same props, you should wrap it in React Memo and use it in your React application. As a result, performance will be improved since the outcome will be remembered.
  • Utilizes the most recent rendered result: Because the component has been memoized, React will omit to render it and instead utilize the most recent rendered result.
  • Only looks for prop changes: which implies that a new render will only be produced if the props are passed on to the component get changed. You will always obtain the memoized result if the props are unchanged.
  • Effect on React Hooks: When the state or context of your component changes, if your component utilizes hooks like useState, useReducer, or useContext, it will still re-render.

Where to use React Memo?

For the majority of your application's components, adopting this memoization strategy is quite simple to get started with. But we should be aware that this approach simply exists to improve performance.

Here are some important points to note on where to use them :

  • Use it if you're only using a functional component. This indicates that your component does not use classes and is assigned the same props. It always produces the same result.
  • Use it when you know ahead of time that a component will be rendered frequently.
  • Use it if the re-rendering uses the same props as the component. If the props change, it's not a good idea to use memoization here.
  • Use it if your component has a large enough number of UI elements for React to perform a props equality check. Very short components with only one heading will not suffice.

Let's take a closer look at point 3 above with an example. This is one of the best applications for React Memo. Typically, in your React apps, a situation occurs that forces a component to render with the same props as a parent component. For example, the parent component SongsViews shown below displays the number of views for a song in an application :

Make sure you notice that:

We made it a functional component, not a class component. We passed on three props to it :

  • title
  • genre
  • viewCount

In a practical sense, here’s how it will render:

It is evident that the parent component SongViews renders each time the viewCount prop is updated with a new value. With this, the child component of Song is also triggered to render even if the other two properties of title and genre stay constant throughout!

Thus, we have a fantastic opportunity to apply some memoization to the child Song component in this situation, preventing pointless re-rendering and enhancing the app's overall efficiency.

Where NOT to use React Memo?

You now know when to utilize React Memo, so let's look at when we should avoid using it excessively or incorrectly. To put it simply, you shouldn't utilize React Memo in all React component that uses the shouldComponentUpdate() method. This is due to the fact that it always returns true by default. The shouldComponentUpdate() method, which effectively does a superficial comparison of the state and the props, is implemented in the render modification that results from the use of React Memo.

In addition, the following two situations should be taken into account :

  • If the component is lightweight and renders with varied props overall, avoid using React Memo.
  • It is not recommended to use React Memo to wrap a class-based component because it is undesired. Instead, you can implement the shouldComponentUpdate() method or extend PureComponent.

Note : If a react component delivers the same output given the same state and props, it is said to be pure component.

Using React Memo in Your Application

Let's get started building a React application that makes use of React Memo now that you are fully informed about it. We'll use React.memo to wrap the component for memoizing(). Let's now create a simple demo app to demonstrate how memoization works in React.

But first, observe react memo syntax :

Step 1: Create a New React App

Make sure Node.js is installed on your system before running the following commands to create a new react app where we will use react memo :

Using the Create React App tool, this will bootstrap a new React application and run the default app at http://localhost:3000/ in your default browser.

Now, open the App.js file and remove all of the code that is present. We will begin by creating a simple to-do list app from scratch.

Step 2: Make the App Interface

Our app will include:

  • An input field for users to enter a new to-do item.
  • A button that handles the click event and adds new to-do items to a list.
  • Then comes the actual list of items.

Here's the JSX code we need to return for the elements listed above :

As you can see, we also included the mandatory attributes value and onChange, which enable the input field to receive user-inputted text values and change events, respectively.

We simply have an onClick handler called handleAddTodo attached to the button.

Last but not least, since we are using a component called <Todo /> to get the list items by passing the list attribute to it, we are not using the unordered list tag here to render the list of items.

Step 3: Create Default State, Handlers, and Components

The useState() Hook will be used here to handle the state of our app. Create a functional component called App() that uses useState() to initialize our app with two default values of to-do items food shopping and Do meditation, as shown below :

Also, let us use useState() once more to initialize the text variable (which receives the actual value) for the input field as follows :

Following that, we received our two handler functions. Let's take care of them. The first is handleText(), which simply changes the value in the input field :

The second is handleAddTodo(), which will be used to concatenate the array value and add it to the list as a title text string value :

The <Todo /> component is ready. Pass the list parameter to it and return an <ul> item that maps over the individual item to create a new <TodoItem /> child component :

The new child component will simply return the <li> item with the list title to display after mapping :

At this point, your code should look like the following :

As of right now, Hooks has been successfully used to create a fairly straightforward to-do app. It's acceptable to add 3–4 items. What if, though, our list had hundreds or even thousands of items? Maybe this list was being used by our app to display things that were fetched from a different database or API?

Then, as our program will be rendering a variety of components and elements, performance enhancements must be taken care of in order to prevent a sluggish user experience.

Step 4: Optimizing the Components with React Memo

Now let's shift our focus to remembering some of the helpful elements. The <Todo /> component comes first. Wrap it in React.memo as follows :

Because it is the only component impacted by the change in state, only the <App /> component will re-render as a result of this. As a result, of the <Todo /> component's constant state, the app performs better because fewer unnecessary renderings are performed.

The <Todo /> component automatically updates when the to-do list is modified. By memorizing the <TodoItem /> child component in the manner shown below, we can now go one step further and render only the recently added item to the list rather than the entire list at once.

All of the prior to-dos will no longer change and won't render again. The components impacted by the state change are the ones that will actually re-render.

Let's demonstrate the memoization impact by adding some log statements following the <App />, <Todo />, and <TodoItem /> components as follows :

By doing this we get to know when each of them renders while we add new to-do items. As we can see both the <Todo /> and <TodoItem /> components render only once which is why we used React Memo here!

Usage

Skipping Re-Rendering when Props Are Unchanged

A component is typically re-rendered by React anytime its parent is re-rendered. Memo allows you to build components that React won't re-render when its parent does, as long as the new props match the old props. It is said that such a component is memoized.

To memoize a component, enclose it in a call to the memo and swap out your original component with the value it returns :

Updating a Memoized Component Using State

When its own state changes, a component will still re-render even if it has been memoized. Only props supplied to the component from its parent are subject to memory.

Even without memo, React will skip re-rendering your component if you set a state variable to its current value. Your component function may still be called again, but the outcome will be ignored. 

Updating a Memoized Component Using a Context

A component will still re-render when the context it is utilizing changes, even if it has been memoized. Only props supplied to the component from its parent are subject to memoization.

By dividing your component into two, you may limit the need for re-rendering to situations where only a portion of the context changes. Pass it down to a memoized kid as a prop after reading the necessary information from the outer component's context.

Minimizing Props Changes

When you utilize memo, every time a prop is not shallowly identical to what it was before, your component re-renders. This indicates that React uses the Object.is comparison to compare each prop in your component to its previous value. As you can see, Object.is(3, 3) returns true, whereas Object.is({}, {}) returns false.

Reduce the number of times the props change in the memo to get the most out of it. For example, if the prop is an object, useMemo: to prevent the parent component from recreating it every time.

Make sure the component accepts the bare minimum of information in its props to minimize props updates. It might, for instance, accept a set of values rather than an entire object :

Specifying a Custom Comparison Function

Rarely, it might not be possible to reduce a memoized component's props changes. Then, instead of utilizing shallow equality to compare the old and new properties, React will use a custom comparison function that you supply. The second argument to memo is this function. Only if the new props would produce the same output as the old props should it return true; otherwise, it should return false.

Custom Equality Check of Props

React Memo checks to see if a prop that was passed to the component has changed between the previous and current values. Each passed-in prop is subjected to a cursory comparison by the default function. It verifies that new values and existing ones are equivalent.

The existing states of signedIn and post are compared to their incoming states in our React.memo(Post) memo. The memoized value is kept and re-rendering is avoided if both values for each prop are equal. If not, the updated value is cached and <Post /> is rendered again.

Custom Comparators :

By including a comparator function as a second argument, the comparison can also be customized:

Conclusion

  • The React.memo is a function that you can use to enhance the render efficiency of hooks and pure function components.
  • React memo is a higher-order component.
  • If the component is lightweight and renders with varied props overall, avoid using React Memo.
  • It is not recommended to use React Memo to wrap a class-based component. Instead, you can implement the shouldComponentUpdate().
  • Memo allows you to build components that React won't re-render when its parent does, as long as the new props match the old props.
  • By dividing your component into two, you may limit the need for re-rendering to situations where only a portion of the context changes.
  • Reduce the number of times the props change in the memo to get the most out of it.