# memo, useMemo, useCallback

## memo

As you know by now, if a parent component renders child component, and if any of the parent component's state or prop changes, it will trigger a re-rendering including all of the recursive child.

```javascript
function Child() {
    console.log("Child component being rendered");
    
    return (
        <h1>This is the child component</h1>
    )
}

function Parent() {
    const [counter, setCounter] = useState(0);
    
    console.log("Parent component being rendered");
    
    return (
        <div>
            <p>This is the parent component {counter}</p>
            <button onClick={() => setCounter(counter + 1)}>Increments</button>
            <Child />
        </div>
    )
}


export default function App() {
    return (
        <Parent />
    )
}
```

That is given the above code snippet, if you click on the button to increment, it will trigger the following print out in the console:

```
Parent component being rendered
Child component being rendered
```

This should tell you that even though the `counter` state is not being used in the Child component, it still triggered a rendering because of the fact stated above.

Now what if you have a really expensive Child, and you don't want it to trigger a re-rendering if it isn't necessary? You can leverage `memo` which allow you to skip re-rendering of a component when it's props are unchanged. In this case we would like to memorize the Child and skip the re-rendering in the case that the parent component's state changes.

<p class="callout info">Alternatively, and always preferred you should consider lifting your content up that is pointed out here [React Parent and Child Component](https://wiki.tamarinne.me/books/react-basics/page/react-parent-and-child-component "React Parent and Child Component"), which also accomplish the same thing, avoiding the re-rendering of the Child component in the case that the state of the Parent component changes.</p>

### How to use Memo

To use `memo` you just need to pass the Component that you wish to memorize into the call, it will return you the memorized version of your component and will usually not be re-rendered when its parent component is re-rendering.

<p class="callout warning">Do note that, React doesn't guarantee that the re-rendering will 100% not happen, it is a performance optimization not a guarantee.</p>

In our example, if we want to skip the re-rendering we would just wrap our Child component in the call and then use it the same way as before.

```javascript
function Child() {
    console.log("Child component being rendered");
    
    return (
        <h1>This is the child component</h1>
    )
}

const MemorizedChild = memo(Child);

function Parent() {
    const [counter, setCounter] = useState(0);
    
    console.log("Parent component being rendered");
    
    return (
        <div>
            <p>This is the parent component {counter}</p>
            <button onClick={() => setCounter(counter + 1)}>Increments</button>
            <MemorizedChild />
        </div>
    )
}


export default function App() {
    return (
        <Parent />
    )
}
```

Now if you click on increment, only the Parent component will re-render the Child component will not because there are no prop changes that will result in the Child needing to be updated.

### Second parameter

`memo(Component, arePropsEqual)`

If you take a look at `memo` you will see that there is a second parameter that you can provide for the memorization call.

The second parameter is a function that accepts two arguments, the component's previous props, and its new props. It should return `true` if the old and new props are equal: Which means the component will not be re-rendered, otherwise, it should return `false`, indicating that the function should be re-rendered.

This second argument gives you more control on exactly when to expire the old component and re-render the memorized component.

## useMemo / useCallback

Going to be grouping these two together because they are really similar, `useCallback` is actually a syntactic sugar for `useMemo`.

 By definition:

- `useMemo`: Caches the result of a calculation between re-renders
- `useCallback`: Caches a function definition between re-renders

They have similar function signature being:

```javascript
const cached = useMemo(calculateValue, dependencies)
const cached = useCallback(fn, dependencies)
```

- calculateValue: **Being the function that computes the final value that you're aching. It takes in no argument and should return a value of any type.** On the first render, React will call this function to retrieve the initial value, on next render, React will check if any of the dependencies have changed since the last render, if it hasn't it will return the same value, otherwise, it will call the function again and give you the new value and caching it
- fn: Similar idea, instead of value, it will be the function that you would want to cache. **This function can take in any number of arguments and return any value.** React during the first render will return this function back to you, then on the next render, React will check if any of the dependencies have changed since the last render, if it hasn't it will return you the same function, otherwise, it will return you the updated function.

<p class="callout info">With newer React compiler, the optimization is actually done for you automatically hence you don't need to call these yourself anymore</p>

### Using useMemo and useCallback

With `useMemo` a great use case of this is to cache an expensive operation. Say you need to sort through a list and that list is huge but it doesn't change often, you would 100% want to leverage `useMemo` to cache the result of the sort to avoid re-calculating the same value when the component is re-rendered, otherwise your application might not be responsive to the user.

```java
function sort(array) {
  // expensive sorting
}

const cached = useMemo(() => sort(input), [input]);
```

With `useCallback`, like it was mentioned, it is just a syntactic sugar on `useMemo`, `useMemo(() => helloWorld, [])` is functionallity

```javascript
function helloWorld() {
}

useMemo(() => helloWorld, []); // Returns you a function as value that you would want to cache
useCallback(helloWorld, []); // Takes in the function as value that you want to cache, they are equivalent
```

`useCallback` is especially useful for skipping re-rendering of components.

Say we again have the same Parent and Child component relationship again.

```javascript
function ProductPage({ productId, referrer, theme }) {
  // Every time the theme changes, this will be a different function...
  function handleSubmit(orderDetails) {
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }

  return (
    <div className={theme}>
      {/* ... so ShippingForm's props will never be the same, and it will re-render every time */}
      <ShippingForm onSubmit={handleSubmit} />
    </div>
  );
}
```

Don't worry about the actual working of the Component, focus on the `handleSubmit` function. Now in Javascript, whenever you run `function() {}` or `() => {}` this always triggers a new reference being created, that means, whenever `ProductPage` is being rendered (when any of its prop or state changes), `handleSubmit` will be re-created with a new definition.

And that means `ShippingForm` will be re-rendered as well because the prop changed. Now this is where `useCallback` comes in handy, because it caches the function result for you allowing `ShippingForm` to skip re-rendering if you combine it with the [memo](#bkmrk-memo) technique that was discussed.

If you **only** use [memo](#bkmrk-memo) it will not work because like was mentioned, `function() {}` or `() => {}` triggers a new function definition every time it is encountered. So if you want to skip re-rendering of the Child then you will want to do both, `useCallback` to cache the function, then use `memo` to skip re-rendering of the Child component because the prop didn't change.

```javascript
import { memo, useCallback, useState } from "react";


function Child({onSubmit}) {
    console.log("Child component being rendered");
    
    return (
        <div>
            <h1>This is the child component</h1>
            {onSubmit()}
        </div>
    )
}

const MemorizedChild = memo(Child);


function Parent({theme}) {
    const [counter, setCounter] = useState(0);
    
    console.log("Parent component being rendered");
    
    const cached = useCallback(() => {
        return (
            <h1>Hello world {counter}</h1>
        )
    }, [counter])
    
    return (
        <div>
            <p>This is the parent component {counter}</p>
            <button onClick={() => setCounter(counter + 1)}>Increments</button>
            <MemorizedChild onSubmit={cached} />
        </div>
    )
}


export default function App() {
    const [theme, setTheme] = useState("dark");
    
    return (
        <div>
            <Parent theme={theme}/>
            <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>Toggle Theme</button>
        </div>
    )
}
```