每次调用 setState
时,React是否重新渲染所有组件和子组件?
如果是这样,为什么?我认为这个想法是React只在需要的时候渲染 - 当状态改变时 .
在下面的简单示例中,两个类在单击文本时再次呈现,尽管状态在后续单击时不会更改,因为onClick处理程序始终将 state
设置为相同的值:
this.setState({'test':'me'});
我希望渲染只会在 state
数据发生变化时才会发生 .
以下是示例代码as a JS Fiddle和嵌入代码段:
var TimeInChild = React.createClass({
render: function() {
var t = new Date().getTime();
return (
<p>Time in child:{t}</p>
);
}
});
var Main = React.createClass({
onTest: function() {
this.setState({'test':'me'});
},
render: function() {
var currentTime = new Date().getTime();
return (
<div onClick={this.onTest}>
<p>Time in main:{currentTime}</p>
<p>Click me to update time</p>
<TimeInChild/>
</div>
);
}
});
ReactDOM.render(<Main/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
[1]: http://jsfiddle.net/fp2tncmb/2/
3 回答
是 . 每当我们调用setState时它调用render()方法,而当“shouldComponentUpdate”返回false时 .
不,当状态发生变化时,React不会渲染所有内容 .
每当组件变脏(其状态发生变化)时,该组件及其子组件将被重新呈现 . 这在某种程度上是尽可能少地重新渲染 . 渲染的唯一时间是't called is when some branch is moved to another root, where theoretically we don't需要重新渲染任何东西 . 在您的示例中,
TimeInChild
是Main
的子组件,因此当Main
的状态发生更改时,它也会重新呈现 .React不比较状态数据 . 调用
setState
时,它会将组件标记为脏(这意味着需要重新渲染) . 需要注意的重要一点是,尽管调用了组件的render
方法,但只有当输出与当前DOM树不同时才会更新真正的DOM(在虚拟DOM树和文档的DOM树之间进行区分) . 在您的示例中,即使state
数据没有't changed, the time of last change did, making Virtual DOM different from document'的DOM,因此HTML也会更新 .默认情况下 - 是的 .
有一个方法 boolean shouldComponentUpdate(object nextProps, object nextState) ,每个组件都有这个方法,它负责确定“应该组件更新(运行渲染功能)?”每次更改状态或从父组件传递新的道具时 .
您可以为组件编写自己的shouldComponentUpdate方法实现,但默认实现始终返回true - 意味着始终重新运行render函数 .
引自官方文档http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
问题的下一部分:
我们称之为“渲染”的步骤分为两步:
Virtual DOM render:当调用render方法时,它返回组件的新虚拟dom结构 . 正如我之前提到的,当你调用setState()时总会调用这个render方法,因为默认情况下shouldComponentUpdate总是返回true . 因此,默认情况下,React中没有优化 .
本机DOM渲染:只有在虚拟DOM中更改它们并且根据需要更改时,React才会更改浏览器中的真实DOM节点 - 这就是React的优秀功能,它可以优化真正的DOM突变并使React快速运行 .