React 重渲染的逻辑是「父组件渲染,子组件无条件跟着渲染」。useMemo/useMemo 的作用是缓存:useMemo(() => heavyCalc(a, b), [a, b]) 依赖不变时返回缓存结果避免重算;useCallback(fn, [deps]) 依赖不变时返回同一个函数引用,避免子组件因新函数 prop 而无效重渲染。
正确用法:先测后优化(React DevTools Profiler 找真实瓶颈);昂贵计算配 useMemo;子组件被 memo 包裹且传入函数 prop 时配 useCallback——缓存与 memo 配套才有意义。滥用反而更慢:缓存本身要比较依赖、占用内存,简单场景下缓存成本比重算还高。
const { useMemo, useCallback, memo, useState, useEffect } = React;
// 子组件被 memo 包裹:props 不变则不重渲染
const Item = memo(function Item({ onClick, label }) {
console.log('Item 渲染'); // 父无脑渲染时这里也会刷
return <button onClick={onClick}>{label}</button>;
});
function List() {
const [q, setQ] = useState('');
const [n, setN] = useState(0);
// 昂贵计算:q 不变就不重算
const filtered = useMemo(() => hugeFilter(q), [q]);
// 函数引用稳定:Item 的 props 不变 → 不重渲染
const del = useCallback(id => remove(id), []);
return (
<div>
<input value={q} onChange={e => setQ(e.target.value)} />
<button onClick={() => setN(n + 1)}>n={n}</button>
{filtered.map(x => <Item key={x.id} onClick={del} label={x.t} />)}
</div>
);
}