Memoize or Callback? A Comprehensive Guide to Using useMemo and useCallback in React
Tags: webdev, react, javascript, typescript
Published: 2023-05-10 11:07:21

In React, both `useMemo` and `useCallback` are hooks that are used for optimization purposes. They are designed to improve the performance of your React applications by preventing unnecessary re-renders of components. In this blog post, we'll discuss the differences between `useMemo` and `useCallback`, when to use them, and provide several examples to help you understand their use cases.

## What is `useMemo`?

`useMemo` is a hook that memoizes the result of a function call. It takes two arguments: a function and a dependencies array. The function is only called when one of the dependencies changes. If the dependencies have not changed, the hook returns the previously memoized result.

Here's an example of `useMemo`:

```javascript
import React, { useMemo } from 'react';

function Example({ a, b }) {
  const result = useMemo(() => {
    console.log('calculate result');
    return a * b;
  }, [a, b]);

  return <div>{result}</div>;
}
```

In this example, the `useMemo` hook is used to memoize the result of the calculation `a * b`. The function passed to `useMemo` is only called when `a` or `b` changes. The memoized result is returned and used to render the component.

## What is `useCallback`?

`useCallback` is a hook that memoizes a function. It takes two arguments: a function and a dependencies array. The memoized function is only created when one of the dependencies changes. If the dependencies have not changed, the hook returns the previously memoized function.

Here's an example of `useCallback`:

```javascript
import React, { useCallback } from 'react';

function Example({ onClick }) {
  const handleClick = useCallback(() => {
    console.log('handle click');
    onClick();
  }, [onClick]);

  return <button onClick={handleClick}>Click me</button>;
}
```

In this example, the `useCallback` hook is used to memoize the `handleClick` function. The function passed to `useCallback` is only created when `onClick` changes. The memoized function is returned and used as the `onClick` handler for the button.

## When to use `useMemo`?

Use `useMemo` when you have a heavy computation that needs to be performed in order to render a component. The memoized result can be used as a prop, state, or a part of the component's render output.

For example, if you have a component that renders a list of items and you need to calculate the total price of all items, you can use `useMemo` to memoize the result of the calculation. The memoized result can then be used to render the total price.

```javascript
import React, { useMemo } from 'react';

function List({ items }) {
  const totalPrice = useMemo(() => {
    console.log('calculate total price');
    return items.reduce((acc, item) => acc + item.price, 0);
  }, [items]);

  return (
    <div>
      {items.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
      <div>Total price: {totalPrice}</div>
    </div>
  );
}
```

In this example, the `useMemo` hook is used to memoize the total price of all items. The function passed to `useMemo` is only called when the `items` array changes. The memoized result is returned and used to render the total price.

## When to use `useCallback`?

Use `useCallback` when you have a function that needs to be passed down to child components as a prop, but the function has dependencies that may change frequently. By memoizing the function, you can prevent unnecessary re-renders of child components that use the function as a prop.

For example, if you have a component that renders a list of items and you need to pass down a function to delete an item, you can use `useCallback` to memoize the function. The memoized function can then be passed down as a prop to child components.

```javascript
import React, { useCallback } from 'react';

function List({ items, onDeleteItem }) {
  const handleDeleteItem = useCallback(itemId => {
    console.log(`delete item ${itemId}`);
    onDeleteItem(itemId);
  }, [onDeleteItem]);

  return (
    <div>
      {items.map(item => (
        <div key={item.id}>
          {item.name}
          <button onClick={() => handleDeleteItem(item.id)}>Delete</button>
        </div>
      ))}
    </div>
  );
}
```

In this example, the `useCallback` hook is used to memoize the `handleDeleteItem` function. The function passed to `useCallback` is only created when `onDeleteItem` changes. The memoized function is returned and used as the `onClick` handler for the delete button.

## Conclusion

In conclusion, `useMemo` and `useCallback` are hooks that are used for optimization purposes in React. `useMemo` is used to memoize the result of a function call, while `useCallback` is used to memoize a function. Use `useMemo` when you have a heavy computation that needs to be performed in order to render a component, and use `useCallback` when you have a function that needs to be passed down to child components as a prop, but the function has dependencies that may change frequently. By using these hooks, you can improve the performance of your React applications by preventing unnecessary re-renders of components.