React中useCallback与memo是否需要同时搭配使用?
关于useCallback与memo的配合使用问题
答案很明确:必须同时使用useCallback和memo,二者是配套生效的,缺一不可。
为什么不能只留useCallback?
useCallback的作用仅仅是缓存函数的引用,让父组件重渲染时,传给子组件的回调函数不会每次都变成新的引用。但它管不了子组件的重渲染逻辑——如果子组件没被memo包裹,不管父组件传的props有没有变化,只要父组件重渲染,子组件都会跟着重渲染。哪怕你用useCallback把函数缓存得再好,子组件根本不会去比对props,直接就重渲染了,等于白做缓存。
为什么不能只留memo?
memo的作用是让子组件在props浅比较未发生变化时,跳过重渲染。但如果父组件传给子组件的回调函数没有被useCallback缓存,每次父组件重渲染都会生成一个新的函数引用——memo比对props时会发现这个函数变了,就会触发子组件重渲染,完全起不到优化效果。
看代码更清楚
反例1:只加useCallback,没加memo
function ProductPage({ theme }) { // 用了useCallback缓存函数 const handleSubmit = useCallback((data) => { console.log('提交数据:', data); }, []); // ShippingForm没被memo包裹,父组件theme切换时照样重渲染 return <ShippingForm onSubmit={handleSubmit} />; } function ShippingForm({ onSubmit }) { console.log('ShippingForm 重渲染了'); return <form onSubmit={onSubmit}>...</form>; }
反例2:只加memo,没加useCallback
function ProductPage({ theme }) { // 每次父组件重渲染都会生成新的handleSubmit const handleSubmit = (data) => { console.log('提交数据:', data); }; return <ShippingForm onSubmit={handleSubmit} />; } // 加了memo,但函数每次都是新的,比对不通过,还是会重渲染 const ShippingForm = memo(function ShippingForm({ onSubmit }) { console.log('ShippingForm 重渲染了'); return <form onSubmit={onSubmit}>...</form>; });
正确用法:二者同时使用
function ProductPage({ theme }) { // useCallback缓存函数引用 const handleSubmit = useCallback((data) => { console.log('提交数据:', data); }, []); return <ShippingForm onSubmit={handleSubmit} />; } // memo包裹子组件,开启props比对 const ShippingForm = memo(function ShippingForm({ onSubmit }) { console.log('ShippingForm 重渲染了'); return <form onSubmit={onSubmit}>...</form>; });
总结
memo是子组件的“重渲染开关”:决定子组件要不要根据props变化来判断是否重渲染。useCallback是父组件的“props稳定器”:保证传给子组件的函数props引用不变,让memo的比对能通过。
只有二者配合,才能实现父组件重渲染时,子组件在props未变化的情况下跳过重渲染的优化效果。
内容的提问来源于stack exchange,提问作者ITselect
相关产品推荐
相关产品推荐

