React技术疑问:父组件重渲染时子组件是否总会随之重渲染?
关于React父组件重渲染时子组件的渲染行为解析
嘿,我完全懂你困惑的点——按咱们之前的认知,父组件重渲染时,子组件默认都会跟着重渲染,除非子组件实现了shouldComponentUpdate()(或者函数组件用memo包裹)。但你做的<DynamicParent/>、<StaticParent/>和<Child/>例子里,结果和预期不一样,对吧?
咱们一步步拆解这个问题:
首先先明确React默认的重渲染逻辑:
- 当父组件的状态或props变化触发重渲染时,React会重新执行父组件的
render()方法,生成新的React元素树。 - 接着React会通过diff算法对比新旧元素树,如果新旧子元素的类型、key都匹配,就会复用现有的子组件实例。但默认情况下,不管子组件props有没有变化,只要父组件重渲染,子组件都会跟着重渲染——因为React内置的
shouldComponentUpdate默认返回true。
那你的例子里为什么<StaticParent/>的<Child/>没重渲染?大概率是你在<StaticParent/>里的写法,让每次render()返回的<Child/>元素是同一个引用,比如:
// 在组件外部静态创建Child元素 const PreCreatedChild = <Child />; class StaticParent extends React.Component { render() { // 每次render都返回同一个PreCreatedChild引用 return PreCreatedChild; } }
而<DynamicParent/>是每次render()都重新创建<Child/>元素:
class DynamicParent extends React.Component { render() { // 每次render都生成新的<Child/>元素引用 return <Child />; } }
这时候两者的差异就出现了:
- 对于
<DynamicParent/>,每次重渲染都会生成新的<Child/>元素对象,React会复用子组件实例,但因为父组件传递了“新的元素对象”,即使props没变化,默认也会触发子组件的重渲染。 - 对于
<StaticParent/>,每次render()返回的是同一个<Child/>元素引用,React会直接跳过这个子元素的diff和更新流程,自然不会触发子组件的重渲染。
另外还有一种可能:如果你的<Child/>是PureComponent(类组件)或者用React.memo包裹的函数组件,那么即使父组件传递了新的元素对象,但只要props没变化,子组件也不会重渲染,这也可能是你观察到差异的原因之一。
最后总结一下:
父组件重渲染时,子组件默认会跟着重渲染,除非满足以下任一条件:
- 子组件实现了
shouldComponentUpdate()并返回false,或者是PureComponent/用memo包裹且props无变化 - 父组件
render()中返回的子元素是同一个引用(比如预先在组件外部创建好的元素)
这样是不是就把你遇到的情况捋清楚啦?
内容的提问来源于stack exchange,提问作者Gabriel West
相关产品推荐
相关产品推荐

