react.memo适用于渲染开销大、props稳定且父组件状态常变但与子组件无关的场景;避免内联函数和对象导致无效缓存,应配合usecallback/usememo使用。

React 中子组件频繁重渲染,八成是因为父组件一动,它就跟着动——哪怕传进去的 props 根本没变。React.memo 就是专治这种“躺枪式渲染”的利器,但它不是万能胶,用对场景才真正省资源。
什么时候该用 React.memo?
别一上来就包一层,先看这三类情况是否符合:
- 组件本身渲染开销大:比如内部有大量 DOM 节点、嵌套多层、或做了复杂计算(如格式化长列表、渲染图表)
- props 大部分时间稳定:像配置项、静态文案、ID 等只在特定时机才更新的值
- 父组件状态常变,但和子组件无关:比如顶部有个计数器或搜索框,每次输入都触发父组件重渲染,而子组件只是展示固定数据
为什么加了 memo 还是不停渲染?
常见陷阱就两个:
-
传了内联函数:比如
onClick={() => doSomething()},每次父组件渲染都会生成新函数,memo 浅比较发现引用不同,直接重渲染 -
传了内联对象或数组:比如
style={{ color: 'red' }}或items={[1,2,3]},同样每次都是新引用
解决办法很明确:用 useCallback 缓存函数,用 useMemo 缓存对象/数组,再传给 memo 包裹的子组件。
简单但关键的写法示范
假设你有一个商品卡片组件,只依赖 id 和 title:
const ProductCard = React.memo(({ id, title }) => {
console.log('ProductCard 渲染了');
return <div>{id}: {title}</div>;
});
父组件里这样用才有效:
function ProductList() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
// 处理点击逻辑
}, []);
<p>return (</p><div>
<button onclick="{()"> setCount(c => c + 1)}>计数: {count}</button><productcard id="{1}" title="iPhone"></productcard>
{/* 不要写成:<productcard id="{1}" title="iPhone" onclick="{()"> {}} /> */}
</productcard>
</div>
);
}
要不要自定义比较函数?
默认用 Object.is 做浅比较,够用。只有当你想忽略某些 props 变化(比如只关心 id 和 status,不关心 timestamp),才需要第二个参数:
const MyComponent = React.memo(
({ id, name, timestamp }) => <div>{name}</div>,
(prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.name === nextProps.name
);
多数项目里,不写这个更安全、更易维护。











