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>


当前回答

尽管在这里的许多其他答案中都有说明,但组件应该:

实现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>

其他回答

是的。它只在每次调用setState时调用render()方法,除非shouldComponentUpdate返回false。

“丢失更新”的另一个原因可能是:

如果定义了静态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添加一个初始化的属性,并在第一时间设置它(如果状态被初始化为非空值)。

不,React不会在状态改变时渲染所有内容。

Whenever a component is dirty (its state changed), that component and its children are re-rendered. This, to some extent, is to re-render as little as possible. The only time when render isn't called is when some branch is moved to another root, where theoretically we don't need to re-render anything. In your example, TimeInChild is a child component of Main, so it also gets re-rendered when the state of Main changes. React doesn't compare state data. When setState is called, it marks the component as dirty (which means it needs to be re-rendered). The important thing to note is that although render method of the component is called, the real DOM is only updated if the output is different from the current DOM tree (a.k.a diffing between the Virtual DOM tree and document's DOM tree). In your example, even though the state data hasn't changed, the time of last change did, making Virtual DOM different from the document's DOM, hence why the HTML is updated.

除了这里解释得很清楚的答案,可能还有其他原因导致你在改变道具或状态后没有看到预期的变化:

注意任何事件。preventdefault ();在你想要通过状态\ props改变重新呈现的代码中,因为它将取消此语句之后的任何可取消事件。

并非所有组件。

组件中的状态看起来就像整个APP状态瀑布的来源。

所以改变发生在setState调用的地方。渲染树从那里被调用。如果你使用纯组件,渲染将被跳过。