Use useMemo and useCallback in code optimization – ReactJS

Tram Ho

In this article, we will clarify how to use useMemo and useCallback to optimize performance in React application.

Problem

Do useMemo and useCallback really help optimize performance in React App or do they just make things worse?

How it works

useCallback

useCallback is a Hook introduced in React since version 16.8. useCallback returns a function and an array containing dependencies (variables that are passed from outside to which the function is dependent upon run). useCallback uses a memorization mechanism – remembers the result of a function into memory and returns the function to be remembered in case the dependencies do not change.

Why use useCallback?

Notice the example above, we have ParentComponent and ChildComponent . When you click the button in ParentComponent , this component will be re-rendered due to the state change. As a result, ChildComponent was also re-rendered even though there was no change (props passed in the integer).

useCallback was born to solve this problem. It will remember the function passed and the list of dependencies. Now, when the button is clicked, React will re-render the ParentComponent and compare whether the ChildComponent props have changed for further rendering. Because loggingStatus completely independent of any dependency, its value does not change and ChildComponent will not be re-rendered.

Compare two cases

What is the cost of using useCallback ? If we leave the two useCallback stand alone, we can be sure that useCallback will consume more memory, namely:

  • useCallback must remember the function passed into it
  • useCallback must initialize an array containing the dependencies and remember them

More specifically, on the second component rendering, loggingStatus will be removed from memory and re-initialized. However, with useCallback , we have to just create a new function, and remember the old function of the first render. The same thing happens with dependency arrays. From the performance perspective of memory, it’s clear that useCallback consumes more resources.

how about useMemo?

useMemo has the same mechanism of operation as useCallback , but instead of passing a function, we can pass a function that returns every type of data we want to remember:

initialMyFruit will only be initialized in case the value of a dependency changes.

Summary

Everything has its price, so we need to use useCallback and useMemo wisely to avoid being laughed at by our colleagues.

When to use useCallback and useMemo?

There are two cases as follows:

  • Referential equality
  • These calculations are heavy

Referential equality

Since there is no word in Vietnamese synonymous with “Referential equality”, I will explain this concept a bit. How do React know if there are changes in dependencies, state or props to re-render components? React will compare the following:

It is worth noting that objects, arrays and functions contain the same content but Javascript still understands that these are two different phenomena. For example, you and your neighbor have the same Mercedes-Maybach S650, even though the two cars are exactly the same, it is impossible to understand that the neighbor’s car is yours.

Similarly, when initializing 2 objects, arrays or functions, even though their contents are identical, they are essentially a different memory area, so they will still be two different phenomena.

There are two cases in which React would use Referential equality:

Dependencies lists

Returning to the example above with a little change:

This time, we initialize myObject from ParentComponent and pass it to ChildComponent via props. In addition, useEffect is used to run console.log(myObject) whenever a change from the props is passed. When clicking the Click button at ParentComponent, although there was no change in myObject , ChildComponent was still rendered. The reason for this is the Referential equality mechanism of JavaScript.

This is when useMemo is used:

Heavy calculations, graphs, animation

In fact, in most cases we won’t need to worry about re-render components because React has a very fast processing speed and this optimization will not make too much difference. However, there is a case, useEffect and useMemo should be used to restrict the initialization & execute functions “consume CPU” as shown below:

Conclude

Using APIs like useMemo or useCallback to optimize code is nothing bad. However, overusing “code optimization” without really understanding the problem can make code performance worse. In addition, concepts like useMemo and useCallback can make code complex and difficult to read, reducing the effectiveness of working with team members. My advice is not to mechanically optimize, really understand and apply these APIs appropriately in different situations.

Reference & credits

This article references the ideas of some other articles:

Share the news now

Source : Viblo