React.memo 包装一个组件,使其在 props 与前一次渲染浅相等时跳过重新渲染。默认情况下,每当其父级渲染时,子组件就会重新渲染;memo 在 props 实际未改变时会短路这一过程。
jsx
const Row = React.memo(function Row({ item, onSelect }) {
// re-renders only when `item` or `onSelect` reference changes
return <li onClick={() => onSelect(item.id)}>{item.name}</li>;
});
为什么这很重要
memo 执行浅比较。如果父级在每次渲染时传递一个新的对象/数组/函数,比较总是会失败,memo 也就无法生效:
jsx
function List({ items }) {
// ❌ a NEW function every render → Row's onSelect prop always "changes"
return items.map(i => <Row key={i.id} item={i} onSelect={id => pick(id)} />);
}
通过 useCallback 稳定函数来修复:
jsx
const onSelect = useCallback(id => pick(id), []); // same reference across renders
return items.map(i => <Row key={i.id} item={i} onSelect={onSelect} />);
何时值得使用
- 组件使用相同 props 频繁渲染,且其渲染成本不低(大列表、昂贵的子树)。
何时不值得使用
- 大多数组件成本低;比较本身有成本,盲目地包装所有内容会增加复杂性但没有收益。先用 React DevTools Profiler 进行性能分析,然后对已证实的性能瓶颈进行 memoize——不要盲目 memoize。
