The useCallback()
, useMemo()
, and memo()
hooks are used to optimize your React application using memoization. Which means it avoids useless re-renders. These three functions should not be used indiscriminately, but exclusively in those situations in which their impact is much less than the benefit.
Memoization
To memoize means to memorize a value or function to avoid processing it again if the same input is given. It is generally used to save you the cost of producing the same value over and over again.
Imagine that you want to multiply the numbers - 17 and 19. To get the solution, you would take a pen and paper, perform a manual calculation, and then write down the result, which is 323. But if I ask you to do the multiplication again, you will not have to do the calculation again, you will just have to read the result from the paper. This is called memoization.
As long as I keep asking you for the multiplication of 17 and 19, you can answer the result without calculating it again. You just memorized the result of the calculation.
useCallback()
useCallback()
is a React Hook that returns a memoized version of the provided function. They are not re-rendered when the components are mounted. It is especially useful when transferring functions to child components.
The useCallback function accepts two arguments and returns one function. The first argument is the function to be memoized, and the second argument is an array of dependencies (like useEffect
). The dependencies are used to determine whether the function should be re-generated or not.
Let's take this example with the following component:
import ChildComponent from './ChildComponent'
const MyComponent = () => { const callback = () => { return 'child component text' } return <ChildComponent callback={callback} />}
export default MyComponent
Every time MyComponent
is rendered, React will create a new function called callback()
and pass it to the ChildComponent
, which will then use it to render the text.
To prevent the props from being re-rendered, we can use the useCallback()
hook. It will return a memoized version of the function.
import { useCallback } from 'react'import ChildComponent from './ChildComponent'
const MyComponent = ({ prop }) => { const callback = () => { return 'child component text' } const memoizedCallback = useCallback(callback, [prop]) return <ChildComponent callback={memoizedCallback} />}
Now the MyComponent
will not re-render when prop
changes. It will remain constant. Therefore, ChildComponent will receive the same function as a prop, always, avoiding its re-rendering every time
useMemo()
useMemo()
is a React Hook that is used to memorize the value of a function. The useMemo function accepts two arguments and returns one value. The first argument is the function to be memoized, and the second argument is an array of dependencies. Just like useCallback()
.
import { useMemo } from 'react'
// Ideal for expensive functions, such as factorials or complex calculations.const OtherComponent({value}) => { const memoizedValue = useMemo(()=>getExpensiveValue(value), [value]) return <div>{memoizedValue}</div>}
Again, as long as the value is kept constant, getExpensiveValue()
will not be executed with every rendering of the component, but instead, the memorized value will be returned. As with useEffect()
we can also leave the array empty, instead of value
.
memo()
memo is not a hook, it is a Higher-Order component (HOC), which is a function that takes a component and returns a new component.
Memo checks if the props of a component have changed. If it has, it will return the original component. If not, it will return a memoized version of the component.
import { memo } from 'react'
const MyComponent = ({ id, title }) => { return ( <div> {id} {title} </div> )}
export default memo(MyComponent)
In this example, as long as the id
and title
are kept constant, MyComponent
will not be re-rendered.
Memo
is ideal for components that are expensive to render but are not expensive to re-render. For example, if you have a list of items, you can memoize the list and only re-render it when the list changes. This will save you a lot of performance.
Summary
React is already very performant when it comes to rendering. You only need to use these optimizations when the need arises. To recap:
- Use
useCallback()
to memoize functions. - Use
useMemo()
to memoize values. - Use
memo()
to memoize components.
Now that you know the power of memoization, give it a try!