React Memo

React.memo is a higher-order component (HOC) that optimises performance by preventing unnecessary re-renders of functional components. It works by memoizing the rendered output of a component and only re-rendering it if its props change. This is especially useful in large applications where performance can be impacted by frequent re-renders.

In this tutorial, we will learn how to import React Memo, its syntax, and how to use it in React Applications, with examples.


Importing and Syntax of React Memo

React.memo is imported from React.

</>
Copy
import React, { memo } from 'react';

And it is used to wrap a functional component to optimise its rendering behaviour.

</>
Copy
const MyComponent = memo((props) => {
  return <div>Hello, {props.name}!</div>;
});

export default MyComponent;

Explanation:

  • memo: A higher-order component (HOC) that takes a functional component as an argument.
  • Wrapped Component: The wrapped component only re-renders if its props change based on a shallow comparison.

1. Basic Example: Preventing Unnecessary Re-Renders

In this example, we have a parent component that passes props to a child component. Using React.memo, the child component only re-renders when its props change.

App.js

</>
Copy
import React, { useState, memo } from 'react';

const Child = memo(({ count }) => {
  console.log('Child rendered');
  return <h2>Count: {count}</h2>;
});

function Parent() {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(false);

  return (
    <div>
      <Child count={count} />
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <br />
      <br />
      <button onClick={() => setOtherState(!otherState)}>Toggle Other State</button>
      <p>Other State: {otherState.toString()}</p>
    </div>
  );
}

export default Parent;

Explanation:

  • React.memo: Wraps the Child component to prevent it from re-rendering unnecessarily.
  • Re-Renders: The child component only re-renders when the count prop changes, not when otherState updates.
  • Benefit: Optimizes performance by avoiding redundant renders of the child component.

Output:


2. Example: Memoizing Components with Expensive Computations

In this example, we use React.memo for a component that performs an expensive computation. Memoization ensures that the computation only runs when its props change.

App.js

</>
Copy
import React, { useState, memo } from 'react';

const ExpensiveComponent = memo(({ num }) => {
  console.log('Expensive computation running');
  const calculateSquare = (n) => {
    let result = 0;
    for (let i = 0; i < 100000000; i++) {
      result = n * n;
    }
    return result;
  };

  const square = calculateSquare(num);

  return <h2>Square of {num} is {square}</h2>;
});

function Parent() {
  const [num, setNum] = useState(2);
  const [otherState, setOtherState] = useState(false);

  return (
    <div>
      <ExpensiveComponent num={num} />
      <button onClick={() => setNum(num + 1)}>Increment Number</button>
      <button onClick={() => setOtherState(!otherState)}>Toggle Other State</button>
    </div>
  );
}

export default Parent;

Explanation:

  • ExpensiveComponent: Performs a resource-intensive calculation, memoized to avoid redundant computation.
  • Re-Renders: The component only re-renders when the num prop changes.
  • This approach optimizes performance by skipping expensive computations for unchanged props.

Output:


Conclusion

Using React.memo, you can optimise the performance of React applications by avoiding unnecessary re-renders. This is particularly beneficial for functional components that handle expensive operations or receive frequently changing props.