React如何识别相同组件?两种渲染模式下的状态留存疑问
React组件实例匹配逻辑解析
问题背景
MyComponent包含计数器状态并展示其值:
- 模式A中,切换
hiddenFlag时,第一个MyComponent的状态会被保留; - 模式B中,切换
hiddenFlag时,第二个MyComponent的状态会被保留;
两种模式下,hiddenFlag控制显示的MyComponent数量一致。需要明确React是如何检测相同组件实例的,以及模式A的渲染阶段是否会判定第一个MyComponent为同一实例。
已知React状态变化分为「渲染阶段」(生成虚拟DOM)和「提交阶段」(对比DOM并更新)。
模式A代码
return hiddenFlag ? ( <div> <MyComponent /> </div> ) : ( <div> <MyComponent /> <MyComponent /> </div> );
模式B代码
return ( <div> {!hiddenFlag && <MyComponent />} <MyComponent /> </div> );
核心原理:React的组件实例匹配规则
React判断组件是否为同一实例,核心依赖虚拟DOM树中的位置(层级+顺序),可选的key属性会覆盖位置规则——默认情况下,React优先通过「位置」来匹配前后两次渲染的组件节点。
模式A的匹配逻辑
当hiddenFlag从false切换到true时:
- 渲染前的虚拟DOM结构:
<div>下有两个MyComponent(位置1、位置2); - 渲染后的虚拟DOM结构:
<div>下有一个MyComponent(位置1);
React对比同一层级的节点,发现新结构的第一个MyComponent和旧结构的第一个MyComponent位置完全对应,直接判定为同一实例,保留其状态。旧结构的第二个MyComponent因在新结构中不存在,会被销毁。
反过来,当hiddenFlag从true切换到false时,新结构的第一个MyComponent匹配旧结构的唯一实例,保留状态,第二个则是全新实例。
模式B的匹配逻辑
当hiddenFlag从false切换到true时:
- 渲染前的虚拟DOM结构:
<div>下有两个MyComponent(条件渲染的位置1、固定的位置2); - 渲染后的虚拟DOM结构:
<div>下只有固定的MyComponent(位置1,对应原结构的位置2);
React按位置匹配时,会将新结构的唯一节点和旧结构的第二个节点做匹配,因此旧结构的第一个组件被销毁,第二个组件的状态被保留。
当hiddenFlag从true切换到false时,新结构的第二个节点匹配旧结构的唯一节点,保留状态,第一个则是全新实例。
关于渲染阶段的判定
是的,模式A的渲染阶段中,React生成新虚拟DOM后,会在diff环节通过位置匹配直接判定第一个MyComponent为同一实例,这个判定结果会指导提交阶段的操作——复用现有实例(保留状态)而非重建。
补充:key的作用
如果给MyComponent加上唯一key属性,React会优先用key匹配组件,不再依赖位置。比如模式A中给两个组件分别加key="1"和key="2",切换hiddenFlag时,key="1"的组件状态始终保留,key="2"的组件会被销毁/创建;只要key不变,无论位置如何调整,React都会匹配到同一实例。
内容的提问来源于stack exchange,提问作者tosshie
相关产品推荐
相关产品推荐

