React是否在每次调用setState()时重新渲染所有组件和子组件?
如果有,为什么?我认为React的想法是只渲染需要的部分-当状态改变时。
在下面这个简单的例子中,当文本被点击时,这两个类都会再次呈现,尽管在随后的点击中状态不会改变,因为onClick处理程序总是将状态设置为相同的值:
this.setState({'test':'me'});
我本以为只有在状态数据发生变化时才会发生渲染。
下面是这个例子的代码,作为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>
“丢失更新”的另一个原因可能是:
如果定义了静态getDerivedStateFromProps,则根据官方文档https://reactjs.org/docs/react-component.html#updating在每次更新过程中重新运行它。
如果状态值来自一开始的道具,它会在每次更新中被覆盖。
如果是这个问题,你可以避免在更新过程中设置状态,你应该像这样检查状态参数值
static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}
另一种解决方案是向state添加一个初始化的属性,并在第一时间设置它(如果状态被初始化为非空值)。
尽管在这里的许多其他答案中都有说明,但组件应该:
实现shouldComponentUpdate,只在状态或属性改变时才呈现
切换到扩展一个PureComponent,它已经在内部实现了一个shouldComponentUpdate方法来进行浅比较。
下面是一个使用shouldComponentUpdate的示例,它只适用于这个简单的用例和演示目的。使用此选项时,组件不再在每次单击时重新呈现自身,而是在第一次显示时和单击一次后呈现。
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'});
},
shouldComponentUpdate: function(nextProps, nextState) {
if (this.state == null)
return true;
if (this.state.test == nextState.test)
return false;
return true;
},
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>
“丢失更新”的另一个原因可能是:
如果定义了静态getDerivedStateFromProps,则根据官方文档https://reactjs.org/docs/react-component.html#updating在每次更新过程中重新运行它。
如果状态值来自一开始的道具,它会在每次更新中被覆盖。
如果是这个问题,你可以避免在更新过程中设置状态,你应该像这样检查状态参数值
static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}
另一种解决方案是向state添加一个初始化的属性,并在第一时间设置它(如果状态被初始化为非空值)。