memo, useMemo and useCallback ftw
Tags: javascript, react, programming, webdev
Published: 2023-05-03 16:36:15

# Memo, useMemo and useCallback ftw

Memoization is a technique in React that optimizes the performance of the application by caching the results of expensive functions and reusing them when the inputs to those functions have not changed. Memoization is achieved in React through the use of the `memo` Higher Order Component (HOC).

The `memo` HOC is used to wrap a component and control its re-rendering. It does this by comparing the props passed to the component during rendering with the props passed during the previous render. If the props have not changed, the component is not re-rendered, and the cached result is used instead.

Here are some cases when you should use `memo` in React:

## 1. Pure Functional Components

If your component is a pure functional component, meaning that it only accepts props and does not have any internal state, then you should use `memo` to cache the result of rendering the component.

## 2. Expensive Rendering

If your component has an expensive rendering process, such as a large number of nested child components, you should use `memo` to cache the result of rendering the component. This will reduce the number of times the component is re-rendered and improve the performance of your application.

## 3. Component with Static Props

If your component receives static props that do not change during the lifecycle of the component, you should use `memo` to cache the result of rendering the component. This will prevent unnecessary re-renders and improve the performance of your application.

## 4. Avoiding Re-renders

If your component does not need to be re-rendered when certain props change, you can use `memo` to prevent the re-rendering of the component. This is useful when you have a component with a large number of child components, and you want to optimize the performance of the application by reducing the number of re-renders.

In conclusion, `memo` is a powerful tool in React that can significantly improve the performance of your application. You should use it when you have pure functional components, expensive rendering processes, static props, or when you want to avoid unnecessary re-renders.

### Examples of using

### Header component

```jsx
import React, { memo } from 'react'

interface HeaderProps {
	name: string
	profileImageUrl: string
}

const Header = ({name, profileImageUrl}: HeaderProps) => {
	return (
		<div>
			<label> {name} </label>
			<img src={profileImageUrl} alt="Picture of a person" />
		</div>
	) 
}

export default memo(Header)
```

### Parent component

```jsx
import React, { memo, useState } from 'react'
import Header from './Header'

export default function App(){
	return (
		<div>
			<Header name="Yoshi" profileImageUrl="https://avatars.githubusercontent.com/u/9868584?v=4"  /> 
		</div>
	)
}
```

### Important alert

React does a shallow comparison of the props. It means, if you have primitive values like string, number, boolean or null, the memo will work well because react will compare by the value. When you pass an object or an array through the component as a prop, it will compare by the reference. So, when you pass an object as a parameter, react will ever create a new reference to the object even tough the new object has the same value of the previous object. So, you have to make like this:

```jsx
import React, { memo } from 'react';

const MyComponent = ({params}) => {
	return <div style={{ backgroundColor: params.color}} />
}

const MemoComponent = memo(MyComponent, (prevProps, nextProps) => {
	return prevProps.params.color === nexProps.params.color //color is a primitive type
})

export default MemoComponent;

```

```jsx
import React, {useState} from 'react';
import MemoComponent from './MemoComponent';

const ParentComponent = () => {
		const [color, setColor] = useState("blue")

    return (
        <div>
            <h1>My Parent Component</h1>
            <MemoComponent params={{color}} />
						<button onClick={() => setColor(color === "blue" ? "red": "blue")} />
        </div>
    );
};

export default ParentComponent;

```

# In the end of the day

You don't need to compare the object atributes, just use useMemo

Here's an example of using useMemo in a React component:

```jsx
import React, { useMemo, useState } from 'react';

const MyComponent = ({ items }) => {
  const [searchTerm, setSearchTerm] = useState('');

  // Memoize the filtered list of items
  const filteredItems = useMemo(() => {
    return items.filter(item => item.includes(searchTerm));
  }, [items, searchTerm]);

  return (
    <div>
      <input type="text" value={searchTerm} onChange={e => setSearchTerm(e.target.value)} />
      <ul>
        {filteredItems.map(item => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default MyComponent;

```

In this example, we have a component that receives a list of items as a prop. We use the `useMemo` hook to memoize the filtered list of items based on the `items` array and the `searchTerm` state. This means that the filtered list will only be recalculated when either the `items` array or the `searchTerm` state changes.

### Best practices using useMemo

Bad: 

```jsx
const sum = useMemo(() => number1 + number2, [number1, number2])
```

Sum is a primitive value (number). You should use like:

```jsx
const sum = number1 + number2;
```

Same thing for strings

Bad:

```jsx
const user = useMemo(() => `${name}, ${age}`, [name, age])
```

User is a primitive value (string). You should use like:

```jsx
const user = `${name}, ${age}`
```

but, when we have cases like that, you should use memo to cache the operation

Good:

```jsx
const sum = useMemo(() => numbers.reduce((a, v) => a + v, 0), [numbers])
```

Sum still being a primitive value but we don't know how big is the `number` array. So the Array.reduce will run just when `number` changes, not in all renders, improving the app performance. :) 

You can maintain the object reference identity just doing:

```jsx
const sum = useMemo(() => {
	first,
	last,
	full: `${first} ${last}`
}, [first, last])
```

# About useCallback

Like useMemo, you can useCallback to maintain function references 

Here is an example of using `useCallback` in a React component:

```jsx
import React, { useState, useCallback } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  // Memoize the increment function
  const increment = useCallback(() => {
    setCount(currentCount => currentCount + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default MyComponent;

```

In this example, we have a component that displays a count and a button to increment the count. We use the `useCallback` hook to memoize the `increment` function based on the `setCount` function. This means that the `increment` function will only be recreated when the `setCount` function changes.

### Best practices using useCallback

You should use `useCallback` when you need to memoize a function that is passed down to child components as a prop. This will prevent the child components from needlessly re-rendering when the function reference changes.

Bad:

```jsx
const handleClick = () => {
  // do something
};

return <MyButton onClick={handleClick} />;

```

In this example, the `handleClick` function is recreated on every render. This means that `MyButton` will be needlessly re-rendered every time the parent component re-renders.

Good:

```jsx
const handleClick = useCallback(() => {
  // do something
}, []);

return <MyButton onClick={handleClick} />;

```

In this example, the `handleClick` function is memoized using `useCallback`. This means that `MyButton` will only re-render if the props passed to it change, rather than every time the parent component re-renders.

### When to use useMemo vs useCallback

You should use `useMemo` when you need to memoize a value that is expensive to calculate. You should use `useCallback` when you need to memoize a function that is passed down to child components as a prop.

In general, you should use `useMemo` for values and `useCallback` for functions.

Now you don't have problems anymore. Hugs.