Does React re-render all components and sub components every time setState()
is called?
If so, why? I thought the idea was that React only rendered as little as needed - when state changed.
In the following simple example, both classes render again when the text is clicked, despite the fact that the state doesn't change on subsequent clicks, as the onClick handler always sets the state
to the same value:
this.setState({'test':'me'});
I would've expected that renders would only happen if state
data had changed.
Here's the code of the example, as a JS Fiddle, and embedded snippet:
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);
_x000D_
<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>
_x000D_
This question is related to
javascript
reactjs
No, React doesn't render everything when the state changes.
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.
Not All Components.
the state
in component looks like the source of the waterfall of state of the whole APP.
So the change happens from where the setState called. The tree of renders
then get called from there. If you've used pure component, the render
will be skipped.
Another reason for "lost update" can be the next:
If it is the problem then U can avoid setting the state during update, you should check the state parameter value like this
static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}
Another solution is add a initialized property to state, and set it up in the first time (if the state is initialized to non null value.)
Yes. It calls the render() method every time we call setState only except when "shouldComponentUpdate" returns false.
Even though it's stated in many of the other answers here, the component should either:
implement shouldComponentUpdate
to render only when state or properties change
switch to extending a PureComponent, which already implements a shouldComponentUpdate
method internally for shallow comparisons.
Here's an example that uses shouldComponentUpdate
, which works only for this simple use case and demonstration purposes. When this is used, the component no longer re-renders itself on each click, and is rendered when first displayed, and after it's been clicked once.
var TimeInChild = React.createClass({_x000D_
render: function() {_x000D_
var t = new Date().getTime();_x000D_
_x000D_
return (_x000D_
<p>Time in child:{t}</p>_x000D_
);_x000D_
}_x000D_
});_x000D_
_x000D_
var Main = React.createClass({_x000D_
onTest: function() {_x000D_
this.setState({'test':'me'});_x000D_
},_x000D_
_x000D_
shouldComponentUpdate: function(nextProps, nextState) {_x000D_
if (this.state == null)_x000D_
return true;_x000D_
_x000D_
if (this.state.test == nextState.test)_x000D_
return false;_x000D_
_x000D_
return true;_x000D_
},_x000D_
_x000D_
render: function() {_x000D_
var currentTime = new Date().getTime();_x000D_
_x000D_
return (_x000D_
<div onClick={this.onTest}>_x000D_
<p>Time in main:{currentTime}</p>_x000D_
<p>Click me to update time</p>_x000D_
<TimeInChild/>_x000D_
</div>_x000D_
);_x000D_
}_x000D_
});_x000D_
_x000D_
ReactDOM.render(<Main/>, document.body);
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
_x000D_
It seems that the accepted answers are no longer the case when using React hooks. You can see in this code sandbox that the class component is rerendered when the state is set to the same value, while in the function component, setting the state to the same value doesn't cause a rerender.
Source: Stackoverflow.com