
当父组件更新导致子组件重渲染时,即使子组件的 props 未变化,也可通过 react.memo 包裹子组件来优化性能,配合 usecallback 正确使用可彻底避免无效渲染。
当父组件更新导致子组件重渲染时,即使子组件的 props 未变化,也可通过 react.memo 包裹子组件来优化性能,配合 usecallback 正确使用可彻底避免无效渲染。
在 React 中,父组件重渲染会默认触发所有子组件的重渲染——这是框架的默认行为,与子组件 props 是否实际变化无关。你已在 App 中对 handleInputChange 和 handleIncrement 使用了 useCallback,这确实保证了回调函数引用的稳定性,但仅靠它无法阻止 ChildComponent 的重渲染,因为每当 anotherProp 更新,App 自身就会重新执行(即重渲染),其 JSX 返回的 节点也会被重新创建并比对,从而触发子组件生命周期(包括 console.log("Child Component renders"))。
要真正跳过子组件的渲染,需满足两个条件:
-
子组件 props 浅层不变(已由
useCallback保障函数引用稳定); -
子组件自身具备“记忆性” —— 即用
React.memo进行包裹。
✅ 正确做法:在 ChildComponent.js 中导出时添加 memo:
import { memo } from 'react';
function ChildComponent({ title, handleInputChange }) {
console.log("Child Component renders");
return (
<input type="text" onchange="{handleInputChange}"><h1>{title}</h1>
>
);
}
export default memo(ChildComponent);
⚠️ 注意事项:
-
React.memo默认执行 props 的浅比较(shallow comparison)。若传入对象、数组等引用类型 props,且每次父组件渲染都新建实例(如useMemo(() => ({ x: 1 }), [])是安全的,但{{x: 1}}则不安全),仍会导致误判为“变化”,进而重渲染。 -
useCallback的依赖数组必须准确:你原代码中handleInputChange的依赖[pageTitle]是冗余的——该回调内部并未读取pageTitle,仅调用setPageTitle(e.target.value)。应简化为[],否则pageTitle变化时会重建函数,破坏引用稳定性:
const handleInputChange = useCallback( (e) => setPageTitle(e.target.value), [] // ✅ 无需依赖 pageTitle );
? 进阶提示:如需自定义比较逻辑(例如忽略某个 prop),可传入第二个参数:
export default memo(ChildComponent, (prevProps, nextProps) => {
return prevProps.title === nextProps.title &&
prevProps.handleInputChange === nextProps.handleInputChange;
});
总结:useCallback 解决的是 函数引用稳定问题,而 React.memo 解决的是 子组件渲染跳过问题,二者协同使用才是防止无效重渲染的完整方案。











