useMemo vs useCallback
Tags: webdev, react, javascript, typescript
Published: 2023-02-12 15:42:11

useMemo and useCallback are two of the react hooks that help us in optimizing the performance of our application whenever components are re-rendered. They can be very useful in case you want to prevent some expensive computations from happening in your application (eg. an api call to the server that does some expensive calculations). 

In this article, we will take a look on how to use these two hooks, what kind of problem do they solve and the difference between the two.

## useMemo

The useMemo hook is used to return a memoized value. Memoization is a popular concept that refers to returning or reusing a cached value instead of computing it every time given the parameters used to calculate the value have not changed from the previous computation. 

The official syntax of useMemo is useMemo(expensiveFunction, [dependencies]). From the syntax we can see that useMemo takes in two arguments. First argument is the expensive function call that we want to avoid while re-render of our component. This function should be pure, cannot take any arguments and the result of this function could be of any type. The second argument is a list of dependencies. 

The function that is passed to useMemo is called during first time render of our component. Subsequent re-runs would depend on the list of dependencies that have been passed to the useMemo hook. If the dependencies have not changed, the old value is reused otherwise new value will be calculated. If no dependencies are passed, the expensive function will be called on each render.

### Example

```
import { useMemo } from 'react';

function UserList({ users, profile }) {
  const activeUsers = useMemo(() => filterActiveUsers(users, profile), [users]);
}
```

In the above example, we have received users as a prop inside our component. Let us say that filterActiveUsers is a very expensive method call that takes in too long time to give a result. If we want to stop the expensive method to re run everytime our UserList component is rendered, we can use useMemo to stop this function from running the next time given that the dependencies (users and profile in this case) do not change.

## useCallback

The useCallback is used to return a memoized version of a callback. It's typical use case is when a child component expects a callback from a parent component and we want to prevent unnecessary re-renders of a child component. 

The syntax of useCallback is useCallback(function, [dependencies]). As we can see, it is very similar to useMemo as in they both take a function as a first argument and takes in a list of dependencies as the second argument. The function definition that we pass in as the first parameter is cached and it can also take in some arguments which can be used for our business logic.

React returns (not call) the function that is passed as an argument to the useCallback hook on first render. The next time when this component re-renders, react checks the dependency list and will only compute the definition if the list of dependencies have changed from the last render. 

### Example

```
import { useCallback } from 'react';

export default function Cart({ productId, userId, orderDetails }) {
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      userId,
      orderDetails,
    });
  }, [productId, userId, orderDetails]);

return (
    <div>
      <Shipping onSubmit={handleSubmit} />
    </div>
  );

```

In the above example, useCallback returns a function that can take in orderDetails as an argument. The function definition is stored inside handleSubmit. This function can in turn be passed to the child component (Shipping). The child component can then use this function. The function definition is cached and will only be recomputed in case the dependencies change on subsequent re-renders.

## Be careful! Do not overuse these methods!

While these two hooks provide a solution to a real problem, we should be careful that we don't use them at the wrong place or overuse them.

For instance, there is no need to memoize a function that’s doing some basic calculation. We should only use useMemo when we know that a function will be very expensive either in terms of time of computation or in terms of the usage of resources. The results of useMemo gets stored in memory and can stay their for long time which in the long run may harm the performance of your application.

With useCallback as well there could be similar problems that we could create if we start caching simple function definitions. As these functions will stay in memory for longer periods of time and will not get garbage collected which in turn will again harm the performance of your application.

## Key differences between useMemo and useCallback

- useMemo is used to store the return value of a function in memory whereas useCallback is used to store the definition of a function.
- The function passed to useMemo cannot take any arguments whereas the function in the useCallback hook can take parameters.
- The function passed to useMemo is called on component render and it's returned value is cached in memory whereas useCallback just returns the function you passed to it but does not call it on component render.