组件呈现以下React元素树。
<div>
<Counter />
</div>
然后发生状态或道具更改并触发渲染,从而生成以下React元素树。
<span>
<Counter />
</span>
Counter
组件的实例是否会被完全重新实例化,构造函数和所有组件?
如果是这样,这种相同的行为是否适用于非根节点,例如:
<div>
<div>
<Counter />
</div>
</div>
过渡到......
<div>
<span>
<Counter />
</span>
</div>
答案 0 :(得分:1)
是的,它将在
上重新实例化Couter
组件
<div>
<Counter />
</div>
到
<span>
<Counter />
</span>
Reconciliation中指定的流程说:
这将摧毁旧柜台并重新安装新柜台。
对于第二个示例,它将首先比较<div>
,但没有变化,但下一个是与上面相同的情况,因此它也remount
Counter
组件。
答案 1 :(得分:0)
每当根元素具有不同类型时,React将会拆除 旧树和从头开始构建新树。从
<a>
开始<img>
,或<Article>
至<Comment>
,或<Button>
至<div>
-any
这些将导致完全重建。
所以是的,在这两种情况下,具有新类型的节点下面的所有内容都将被完全重建。
工作演示:
class Inner extends React.Component {
constructor(props) {
super(props);
console.log('Inner constructor called.')
}
render() {
return <p>{`<${this.props.tag}>`}</p>;
}
}
const Container = ({Tag}) => (
<Tag>
<Inner tag={Tag} />
</Tag>
);
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
tag: 'div',
};
}
changeTag = () => this.setState(state => state.tag === 'div' ? {tag: 'span'} : {tag: 'div'});
render() {
return (
<div>
<button onClick={this.changeTag}>Change tag</button>
<Container Tag={this.state.tag} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<div id="root"><!--Filled by React--></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>