Memoize only to skip work
Put work below early returns, keep props stable, skip trivial memos.
React docsreact.dev
If your project has React Compiler enabled, manual memoization with memo() and useMemo() is not necessary.
From vercel-react-best-practices: rerender-memo and 3 more.
useMemo before an early return
Loading is on. Type a name and feel the lag.
useMemo, then returnBad
- computeAvatarId calls
- 0
- while loading
- 0
- main thread blocked
- 0 ms
useMemo(…); if (loading) returnmemo(UserAvatar)Good
- computeAvatarId calls
- 0
- while loading
- 0
- main thread blocked
- 0 ms
if (loading) return; <UserAvatar />const UserAvatar = memo(function UserAvatar({ user }) {
const id = useMemo(() => computeAvatarId(user), [user])
return <Avatar id={id} />
})
function Profile({ user, loading }) {
if (loading) return <Skeleton />
return <div><UserAvatar user={user} /></div>
}
Inline defaults break memo()
Press Start and watch the avatar ring.
Default made in renderBad
00:00
Ada Lovelace
- Header renders
- 0
- UserAvatar renders
- 1
- Object.is(prev.onClick, next.onClick)
- n/a
function Header({ onAvatarClick = () => {} })Hoisted defaultGood
00:00
Ada Lovelace
- Header renders
- 0
- UserAvatar renders
- 1
- Object.is(prev.onClick, next.onClick)
- n/a
const NOOP = () => {} · { onAvatarClick = NOOP }const NOOP = () => {}
function Header({ onAvatarClick = NOOP }) {
const now = useClock()
return <><time>{now}</time><UserAvatar user={user} onClick={onAvatarClick} /></>
}
useMemo costs more than a || b
Pick a render count and run.
Time per renderMeasured
function Header({ user, notifications }) {
const isLoading = user.isLoading || notifications.isLoading
if (isLoading) return <Skeleton />
}
Why it matters, pros and cons
Why it matters
Memo pays only if it skips work. Before a return or with unstable props, it can't.
Pros
- No work for UI that is off screen
- Memoized children stay skipped
- Less code where a hook was overhead
Cons
- React Compiler memoizes for you
- The extracted component recomputes once when it remounts
memo()on cheap components is pure overhead