When do useMemo / useCallback actually help? Why does passing an inline object/function break React.memo?
Whether you memoize for a REASON (identity/expense), not by cargo-cult on everything.
React.memo skips a re-render when props are shallow-equal. But an inline object or function is a NEW reference every render, so shallow-equal fails and memo is defeated. useCallback stabilizes a function's identity; useMemo stabilizes a computed value's (or caches an expensive calc). Use them when (a) a value is an expensive computation, or (b) a reference is passed to a memoized child or an effect's deps. Everywhere else they add cost for no benefit. Three clarifications that separate cargo-cult from judgment: memoization has its own cost (the comparison plus holding the previous value), so wrapping a cheap leaf component buys nothing; useCallback(fn, deps) is exactly useMemo(() => fn, deps), just sugar for functions; and React.memo only compares props — it does nothing about a re-render caused by internal state or a changed context value. The chain has to be complete to work: a memoized child still re-renders if ANY prop is a fresh reference, so stabilizing one callback while passing a new inline object next to it accomplishes nothing. The forward-looking note: the React Compiler (React 19+) memoizes automatically, which will make most manual useMemo/useCallback unnecessary — another reason to reserve them for measured, specific wins today.
Passing callbacks/objects to memoized children, stabilizing effect deps, memoizing genuinely expensive derived data.