The UseMemo Hook.

The Basics

useMemo is your way of telling React to be lazy.

 
Here's how it should be called:
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' change

The calculateValue argument

 
Hmmm, I wonder what calculateValue is?
 
Well, it's a function that calulates value, obviously.
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 useMemoit 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?).

Here's an example:
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.
 
If you want to be able to return complex types (i.e. an object), here's what you should do:
interface UserData {
    id: number;
    name: string;
}

const formattedData = useMemo<UserData>(() => {
    return {
        id: 69,
        name: "Dan"
    }
},[numberA, numberB])