How to use useMemo hook in React?
The useMemo
is a caching hook in React. Memoization or cache a calculated value to avoid recalculation. Recalculate only when its dependencies update.
useMemo() syntax:
const cachedValue = useMemo(() => computeExpensiveValue(a, b), dependencies);
useMemo()
accepts 2 arguments — a function computeExpensiveValue
that compute and returns a value and the depedencies
array:
How useMemo() works?:
- On the first rendering,
useMemo
invokescomputeExpensiveValue
function and caches the calculated value, and returns it to the component. - In the next rendering, if the dependencies do not change, then
useMemo()
does not invokecomputeExpensiveValue
and returns the cached value - If the dependencies change in the next rendering, then
useMemo()
invokescomputeExpensiveValue
and cache the new value, and returns it.
Facts about useMemo():
- It returns a value and not a function
- Spreaded object inside dependencies does not work
- It is difficult to know which dependencies cause re-calculation. We have a few workarounds like these: https://www.npmjs.com/package/@simbathesailor/use-what-changed
- We should not overuse useMemo. In basic Big O(n) cases, we should avoid using useMemo
Example usage of useMemo():
import { useState, useMemo } from "react"; import ReactDOM from "react-dom/client"; const computeExpensiveValue = (num) => { console.log("Calculating..."); for (let i = 0; i < 1000000000; i++) { num += 1; } return num; }; const App = () => { const [count, setCount] = useState(0); const [todos, setTodos] = useState([]); const calculation = useMemo(() => computeExpensiveValue(count), [count]); const increment = () => { setCount((c) => c + 1); }; const addTodo = () => { setTodos((t) => [...t, "New Todo"]); }; return ( <div> <div> <h2>My Todos</h2> {todos.map((todo, index) => { return <p key={index}>{todo}</p>; })} <button onClick={addTodo}>Add Todo</button> </div> <hr /> <div> Count: {count} <button onClick={increment}>+</button> <h2>Expensive Calculation</h2> {calculation} </div> </div> ); };