explanation of useMemo React

Hi, is important to know how can we increment performance in our components that lives in a React application, I have a post where I made mention of react memo well this is a good method to use. Do not confuse “memo” and “useMemo” of React, they are different.

In this post we are going to see the useMemo of react also this is important to implement performance in our components. 

I have a Parent component and a Child component like this:

Then, if in the Parent component have a data that is changing or something that is causing a re-rendering the Parent component then in that case every-time that my Parent component has a re-render also my Child component will have a render too.

The useMemo is util for us if the props that we are passing to our Child components are objects, arrays. As we see if we use “memo” in our child component this will be stop the re-renderings but just in case of primitive values (string, number, bigint, boolean, undefined, and symbol) and in case of those values are the same all the time.

Ok, so let see the code of our Parent component where I’m passing a data array to props of my Child component:

Parent component code:

// Dependencies
import React, { useState, useEffect } from 'react';

// Components
import Child from './child';

// Styles
import './App.css';

function App() {
  console.log('*** Render the PARENT COMPONENT ***');

  // Local state
  const [time, setTime] = useState(new Date().toString());


  // Data array
  const dataArray = ['1', '2', '3'];

  // Just to cause re-rendering
  useEffect(() => {
    // Getting the current date every 1 second
    setInterval(() => {
      setTime(new Date().toString());
    }, 1000)

  }, []); // Acting as component did mount

  return (
    <div className="App">

      <section>
        <h1>I'm Parent component</h1>
        <p>{time}</p>

        <Child dataArray={dataArray} />
      </section>
    </div>
  );
}

export default App;

Then in my Child component I’m receiving dataArray in my props and also I have the “memo” method of React, but if you see the result below you will see that use “memo” is not enough in cases where our props are arrays or object, so in this case we still have re-rendering in our child component event if the data array is the same all the time. 

Child component code:

import React, { memo } from 'react'; // importing memo from react

// Functional component
const Child = ({ dataArray }) => {
  console.log('Render CHILD COMPONENT')

  const divStyle = {
    border: '2px solid green',
    width: '100%',
    height: 'auto'
  }

  return (
    <>
      <section style={divStyle}>
        <p>I'm Child component</p>
      </section>
    </>
  )
}

// Wrapping the component with memo()
export default memo(Child);

Result: The array data values are the same and also we are using memo in our child component. 

Ok, in this case what is happening is that every time that the Parent component is re rendering the dataArray is re made every time and that cause that our child component have re  renderings too also if is using “memo”

Well for this case, the solution to prevent this is implement “useMemo” in our Parent component, to useMemo just wrap the array or object and this will memoize the values of the array and it won’t create the array every single time that the Parent component re render

The first step is import “useMemo” in Parent component

import React, { useMemo } from 'react';

The second step is wrap out array (or object) with useMemo

  // Data array
  const dataArray = useMemo(() => {
    return ['1', '2', '3'];
  }, []);

Nice, our final code will be like this:

Parent component 

// Dependencies
import React, { useState, useEffect, useMemo } from 'react';

// Components
import Child from './child';

// Styles
import './App.css';

function App() {
  console.log('*** Render the PARENT COMPONENT ***');

  // Local state
  const [time, setTime] = useState(new Date().toString());


  // Data array
  const dataArray = useMemo(() => {
    return ['1', '2', '3'];
  }, []);

  // Just to cause re-rendering
  useEffect(() => {
    // Getting the current date every 1 second
    setInterval(() => {
      setTime(new Date().toString());
    }, 1000)

  }, []); // Acting as component did mount

  return (
    <div className="App">

      <section>
        <h1>I'm Parent component</h1>
        <p>{time}</p>

        <Child dataArray={dataArray} />
      </section>
    </div>
  );
}

export default App;

Child component 

// Dependencies
import React, { memo } from 'react'; // importing memo from react

// Functional component
const Child = ({ dataArray }) => {
  console.log('Render CHILD COMPONENT')

  const divStyle = {
    border: '2px solid green',
    width: '100%',
    height: 'auto'
  }

  return (
    <>
      <section style={divStyle}>
        <p>I'm Child component</p>
      </section>
    </>
  )
}

// Wrapping the component with memo()
export default memo(Child);

Result: Now if you see our Child component is render just the default render and not more. 

By Cristina Rojas.