Front end Development
useMemo and useCallback
July 18, 2022
In this article, which is my first post, I wanted to discuss React’s memoization hooks: useMemo and useCallback. I will explain these hooks, which cause confusion for many people regarding where and how they should be used, along with examples.

If you are working on medium or large scale React projects, you have likely encountered these hooks. You might have even used them just because they were already being used in the project without knowing their exact functions; however, I must say that most of these usages are unnecessary and cause memory leaks. Without further ado, let’s talk about useMemo, useCallback, and their actual intended purposes.
Memory Leak: This occurs when a code block finishes its execution but does not release the memory block it occupied.
useMemo
As shown in the example, useMemo takes a “create” function and a dependency array, and returns a memoized value. Continuing with the naming conventions in the example, the memoizedValue variable will keep the same value in memory as long as the a or b values inside the dependency array do not change. If at least one of the a or b values changes, the “create” function executes and returns a new value. It is used to calculate values that take time to compute and could cause performance issues (computationally expensive calculations).
useCallback
useCallback, on the other hand, takes an inline callback and a dependency array as arguments, and returns a memoized callback (a memoized callback function) as its return value. Just like with useMemo, the callback held by the memoizedCallback variable only changes when the a or b variables inside the dependency array change. Additionally, useCallback is useful when passing callback functions to child components that are optimized using the reference equality method to prevent unnecessary re-rendering operations.
Use Cases for useMemo and useCallback
- Referential Equality
- Computationally Expensive Calculations
Using memoization hooks like useMemo and useCallback can introduce overhead. Therefore, they must be used responsibly at points where they are truly needed.
Referential Equality
In the JavaScript language, there are two types of equality operators: abstract equality (==) and strict equality (===). React generally uses the Object.is(object1, object2) equality check, but without going into too much detail, we can say that this structure is highly similar to strict equality.nü kullanır fakat çok detaya girmeden bu yapı ile strict equality’nin oldukça benzer olduğunu söyleyebiliriz.
There are 2 situations in React where referential equality is important. One of them is the dependency array and the other is React.memo.
Dependency Array
Some hooks in React include a dependency array in their structure. The most well known ones can be listed as useEffect, useMemo, and useCallback. If we continue with examples through useEffect (examples are kept simple for clarity):
In the example above, it is intended to trigger useEffect when firstProp and secondProp change, and functionA is expected to run again. However, due to the working logic of JavaScript, propObject will be recreated after every render. For this reason, React will think the variable inside useEffect’s dependency array has changed and will execute useEffect even if firstProp and secondProp have not changed. Because of this, unwanted situations can occur, and it is possible to fix this situation in two different ways.
The first of these, and the solution path I would recommend applying if possible, is as follows:
However, in some cases, the props we pass might not be primitive (string, number, etc.). That is, when they have types like function, object, or array, we can fix the problem mentioned above by using useMemo or useCallback.
This usage style actually demonstrates the reason why useMemo and useCallback hooks emerged.
React.memo
If we proceed through an example again:
As seen in the example, our Counter component contains two components named Button. Every time we click one of the Button components, one of the states inside the Counter component will change, so both Button components will be rendered. While the rendering of the clicked Button component (the one whose value we want to change) does not pose a problem for us since we will access the current count value inside it, the other Button component will be re-rendered unnecessarily. To fix this problem, we need to wrap the Button component with React.memo.
React.memo(component, areEqual) is actually a high order component (higher-order component) and takes 2 arguments as shown. While the first argument is the component we want to wrap, the second argument is a custom comparison function (areEqual) that is optional to use. Additionally, while React.memo normally compares the props inside the component superficially (shallowly compare) to decide on the rendering process, we can customize the comparison process thanks to the areEqual function. For detailed information…
After wrapping it in the manner above, the Button component will be re-rendered only when its props change thanks to React.memo. Right here, we need to fix one more small point because the variables given to onClick from the props of the Button component are of non-primitive (function, object, etc.) type, so they will be recreated after the state change and we won’t be able to prevent the unnecessary rendering operation. To fix this situation, useCallback steps in (useMemo can also be used depending on the situation).
With this change we made, we prevent the unnecessary rendering operation and utilize React.memo in a healthy way.
React.memooptimization can introduce overhead, so we must be sure before deciding to use it and use it correctly. Additionally, thanks to React’s fast working structure, unnecessary rendering operations that do not cause serious problems can be ignored.
Computationally Expensive Calculations
Performing calculations that can introduce overhead inside useMemo will provide us with performance benefits. The main reason for the emergence of useMemo is to avoid such expensive operations during unnecessary repetitions. To give an example again (even if it is not exactly a practical scenario, it is an example I intended to be clear):
As seen in the code lines above, calculatePrimes will run repeatedly during possible rendering operations, and assuming that calculating prime numbers will introduce overhead, it will place a serious load on our project.
When we wrap it with useMemo this way, it will be calculated only in case the values inside the dependency array change. That is, it will not perform calculations during unnecessary rendering operations and will return the calculated value in memory instead.
Conclusion
I would like to emphasize again that while the use of useMemo and useCallback hooks can provide performance benefits, it can also have overhead. Especially for your team members working on the same project, it can cause confusion, or with a mistake you make in the dependency array, you might prevent memoized values from being cleared by the garbage collector, thereby causing performance issues. If you do your measurements and usage correctly, you can achieve performance benefits as I mentioned at the beginning.
I hope it has been a helpful article 🙂
References
- https://medium.com/@jan.hesters/usecallback-vs-usememo-c23ad1dc60
- https://reactjs.org/docs/hooks-reference.html#
- https://www.developerway.com/posts/how-to-use-memo-use-callback
- https://kentcdodds.com/blog/usememo-and-usecallback
- https://dmitripavlutin.com/use-react-memo-wisely/
Author: Mehmet Mutlu