如何避免React父组件状态更新时子组件的不必要重渲染?
如何避免React父组件状态更新时子组件的不必要重渲染?
嘿,看起来你已经尝试用memo来优化子组件渲染了,但还是遇到了父组件更新时子组件跟着跑的问题,我来帮你理清楚问题出在哪,以及怎么解决~
问题原因拆解
先给你捋清楚当前两个子组件的情况:
- 对于
Child2:你没有用memo包裹它,而React的默认逻辑是父组件重渲染时,所有子组件都会跟着重渲染,不管有没有传递props,所以每次点击counter按钮,Child2必然会打印child 2 rerenders。 - 对于
ChildComponent:你已经用memo包裹了,但如果还是看到它打印child renders,大概率是开发环境下React Strict Mode导致的双渲染——React 18的Strict Mode在开发阶段会让组件额外渲染一次,用来帮你提前发现副作用相关的bug,这不是真正的“不必要重渲染”,生产环境打包后这个行为会自动消失。
具体解决方案
1. 给Child2添加memo包裹
要阻止Child2的不必要重渲染,只需要像ChildComponent一样用memo包裹它就行:
// Child2.js import { memo } from "react"; const Child2 = () => { console.log("child 2 rerenders"); return <div>HIii theere</div>; }; export default memo(Child2);
这样当App因counter更新而重渲染时,Child2因为没有props变化,会被memo跳过重渲染。
2. 排查ChildComponent的“异常重渲染”
如果你在开发环境中每次点击counter都看到child renders,先检查你的项目入口文件(比如main.jsx/index.jsx)里,App是不是被StrictMode包裹了:
// 示例入口文件 import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.jsx'; const root = createRoot(document.getElementById('root')); root.render( <StrictMode> <App /> </StrictMode> );
Strict Mode在开发环境下会触发组件两次渲染,这是正常的调试行为,目的是帮你检测组件里的副作用问题。如果暂时不想看到这个效果,你可以先注释掉<StrictMode>标签,这时候再点击counter,你会发现ChildComponent不会再打印child renders了——因为memo已经生效,阻止了它的不必要重渲染。
3. 未来扩展:子组件带props时的优化
如果以后你的子组件需要接收props,要注意避免传递不稳定的引用类型(比如内联函数、内联对象),因为每次父组件重渲染都会创建新的引用,导致memo的浅比较认为props变化了,子组件还是会重渲染。
这时候可以用useCallback包裹函数,useMemo包裹对象,确保引用稳定:
// 父组件App里的例子 const handleChildClick = useCallback(() => { // 你的点击逻辑 }, []); // 依赖数组为空,确保函数引用始终稳定 // 传递给子组件 <ChildComponent onClick={handleChildClick} />
这样就能彻底杜绝子组件的不必要重渲染啦~
备注:内容来源于stack exchange,提问作者Suyash Srivastava
相关产品推荐
相关产品推荐

