iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

useMemo

useMemo memoises an expensive computed value, recomputing only when its dependencies change. Use it for actually-expensive work or to keep referential equality for downstream memo children — not by default.

When to memoise, when not to

EXAMPLE
import { useMemo, useState, memo } from 'react';

// 1) Expensive derivation — list filtering and sorting
function Table({ rows, query }) {
    const filtered = useMemo(() => {
        return rows
            .filter(r => r.name.toLowerCase().includes(query.toLowerCase()))
            .sort((a, b) => a.score - b.score);
    }, [rows, query]);
    return <List items={filtered} />;
}

// 2) Stable reference for a memoised child
const HeavyChild = memo(function HeavyChild({ config }) {
    // ...
});

function Parent({ theme }) {
    // Without useMemo, config is a new object each render → HeavyChild always re-renders
    const config = useMemo(() => ({ theme, threshold: 5 }), [theme]);
    return <HeavyChild config={config} />;
}

// 3) Avoid memoising primitives
// const x = useMemo(() => count + 1, [count]);   // unnecessary — just compute it inline

// 4) Don't memoise everything
// useMemo costs memory + dep-array bookkeeping. For cheap work, raw recomputation wins.

// 5) Pair with useCallback for function props to memoised children
import { useCallback } from 'react';
function Filters({ onSubmit }) {
    const handleClick = useCallback(() => onSubmit(state), [onSubmit, state]);
    return <Button onClick={handleClick} />;
}

// 6) Common bugs

// 6a) Wrong dep array — stale value
// const sorted = useMemo(() => sort(rows), []);  // rows updates ignored

// 6b) Memoising a Date/random/Math.random — non-deterministic
// const now = useMemo(() => Date.now(), []);     // freezes on first render

// 6c) Treating useMemo as a side-effect — never do work with effects inside
// const x = useMemo(() => { fetch(url); return ...; }, []);   // bad

// 7) Profile FIRST. React DevTools → Profiler.
// If a component isn't slow, useMemo just adds noise.

Why it matters

useMemo is a perf tool, not a correctness tool. Reach for it when a computation is measurably expensive or when downstream memo children need stable references — not by default.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
const expensive = useMemo(
    () => bigList.filter(i => i.active).map(transform),
    [bigList],
);
Try it Yourself »

Discussion

Loading…