The UseMemo Hook.
The Basics
useMemo is your way of telling React to be lazy.
useMemo(calculateValue, dependencies)But what does that mean?
useMemo acts as a store of a value. It stores the result of a function so that React doesn't have to re-calculate it every time the component re-renders.
Here's an example. Say we have component that has to render a list of 100,000 items:
function SearchList({ items, query }) {
// This runs on EVERY single render, even if 'items' hasn't changed!
const filteredItems = items.filter(item => item.includes(query));
return <ul>{filteredItems.map(i => <li key={i}>{i}</li>)}</ul>;
}Even if items doesn't change, the filter function will be called every time the component re-renders.
This is, obviously, shit.
The solution in this case is to use useMemo, to store the filtered items array between re-renders.
const filteredItems = useMemo(() => {
return items.filter(item => item.includes(query));
}, [items, query]); // Only re-run if 'items' or 'query' changeThe calculateValue argument
calculateValue is?const addedNumbers = useMemo(() => {
return numberA + numberB;
},[numberA, numberB])In this scenario, if either numberA or numberB change, the function that adds them together will be re-called.Simple, right?
The dependency array argument
This is just the same as the useEffect dependency array. If any of the values in the array change, the calculateValue function will be called.
What if I don't pass a dependency array?
If you don't pass a dependency array to useMemo, it essentially becomes useless.
No dependency array? Then the calculateValue function is called every render. And that's very silly isn't it, because that's what we're trying to avoid here.
What if I pass an empty dependency array?
Another good question,
If you pass an empty dependency array to useEffect, you're telling React:
"Run this code exactly once, and then never touch it again."
With Typescript
Great news! You don't need to explicitly type this.
useMemo also uses type inference (noticing a pattern, yet?).
const addedNumbers = useMemo(() => {
return numberA + numberB;
},[numberA, numberB])This calculateValue function returns a number, so Typescript will infer that it should always return a number.interface UserData {
id: number;
name: string;
}
const formattedData = useMemo<UserData>(() => {
return {
id: 69,
name: "Dan"
}
},[numberA, numberB])