Categories
reactjs

Memoizing with React.useMemo

Hey everyone 👋🏻,

In this article, let us learn about a very special React Hook called as the useMemo hook and understand how and when to use it.

What is the useMemo hook ?

useMemo is a React Hook that was introduced to memoize expensive computations. Let us understand some basics about this. In order to understand the useMemo hook, let us understand its syntax:

const memoResult = useMemo(someFunction, dependencies);

So what happens with useMemo is that when the component renders for the first time, the useMemo hook invokes the someFunction (it could be any function, I am just calling it as someFunction) and memoizes the value that it computes for us and then it returns the result back to the component. Now the interesting thing here is that if during the subsequent renders, the list of dependencies that we specify do NOT change, then in that case useMemo will not invoke the someFunction but instead it will return the memoized value. Contrary to this, if the list of dependencies experience a change during subsequent renders, then useMemo will invoke the someFunction, memoize the result that it gets as a result of computation and then return it back to the component. So in essence, this is what happens in the useMemo hook.

Now let us see a simple example :

Let us say we have a component that deals with computation of factorial of a number, let’s call the component as FactorialResult. Now what this component does is that it computes the factorial of a number that is supplied into the input field by the user. Let us see the basic code for same :

import React from 'react' 
function computeFactorial(num) { 
   if(num == 0) { 
       return 1;
   }
   return num * computeFactorial(num - 1)
}
const FactorialResult = () => { 
  const [num, setNum] = React.useState(0); 
  const factorial = computeFactorial(num); 

  const handleChange = event => { 
         setNum(+event.target.value); 
  }
  return ( 
    <div>
      Factorial of 
      <input type="number" 
       value={num} 
       onChange={handleChange} />
      is {factorial}
    </div>

   );
}

Now every time, you change the input value, the factorial is re-calculated as a result of re-render.
Now how can we memoize this factorial calculation which itself is an expensive operation ? We want to memoize the factorial computation when the component re-renders. So for this we can make use of the useMemo hook. Let us make small changes in our code and memoize this factorial calculation. So here is the new code for the same component :

import React from 'react' 
function computeFactorial(num) { 
   if(num == 0) { 
       return 1;
   }
   return num * computeFactorial(num - 1)
}
const FactorialResult = () => { 
  const [num, setNum] = React.useState(0); 
  const factorial = React.useMemo(() => {
      computeFactorial(num)
   },[num]); 

  const handleChange = event => { 
         setNum(+event.target.value); 
  }
  return ( 
    <div>
      Factorial of 
      <input type="number" 
       value={num} 
       onChange={handleChange} />
      is {factorial}
    </div>

   );
}

Now every time you change the value of the num, the computeFactorial will get invoked but only if the num has changed. If num does not change on the re-render, then it will return the memoized result for its factorial and will not make that extra computeFactorial call. I hope that makes perfect sense.

Let’s see one more example to make the useMemo hook extremely clear.

Let us say we want to return the full name of a person, so for this let us say we have a function in some component that gives us the full name:

const fullName = React.useMemo(() => {
   return firstName + " " + lastName
},[firstName, lastName])

In above code, if the firstName or lastName change, then our fullName function will get re-invoked because we have specified firstName and lastName as dependencies. Please note : functions themselves usually don’t need to be re-computed, and their dependencies are mostly closure values that may change.

const fullName = React.useCallback(() => {
     return firstName + " " + lastName
}, [firstName, lastName]);

Now for above piece of code when firstName or lastName change, we don’t need a separate instance of the function on each re-render of the component, but we need exact the one and same instance of the function so that it has up to date values in the closure.

So this is it for this article. Thanks for reading.

Leave a Reply

Your email address will not be published.