Reputation: 9699
Let's consider the following sample:
import React, {Component} from 'react';
class B extends Component {
render() {
console.log(`Render runs with ${this.props.paramA}`);
return (<div>{this.props.paramA}</div> );
}
}
class App extends Component {
constructor() {
super();
this.state = {paramA: 'asd'};
}
handleChange(event) {
this.setState({paramA: event.target.value});
}
render() {
return (<div>
<input value={this.state.paramA} onChange={e => this.handleChange(e)}/>
<label>
<B paramA={this.state.paramA}></B>
</label>
</div>);
}
}
Here's the gif of how it works.
If you noted, in order to update the changes from properties, react needs to evaluate "render" method. That causes the whole component to update instead of its small part that really changed (check the gif, the div element blinks in chrome developer tools):
TL;DR According to react philosophy,apps should be written in a way to have as many dummy components as possible. That means we have to pass properties a few level down sometimes (other time we can use e.g. redux), which leads to a lot of render
methods that evaluate every time the property of top level component changes. With all that being said I often see in the real life react application that a whole root
div blinks when e.g. users types something into input. Well even if it's a browser "lag" I don't really like the idea that react reevaluates all components (meaning running their render method) when a component needs to update only its small part.
The question: Am I doing something wrong? Is there a way to implement react component so they update only things that changed?
Upvotes: 4
Views: 5734
Reputation: 121
In this case, React is not rerendering the entire component but the first parent of the dynamic part of them. In this case, the <div>
is the parent (and the entire component so you're right), but in this fiddle wrapping {this.props.paramA}
inside a paragraph tag, the <div>
is not the direct parent, so just rerenders <p>
tag and <div>
does not need to update.
class B extends React.Component {
render() {
console.log(`Render runs with ${this.props.paramA}`);
return (<div><p>{this.props.paramA}</p></div> );
}
}
class App extends React.Component {
constructor() {
super();
this.state = {paramA: 'asd'};
}
handleChange(event) {
this.setState({paramA: event.target.value});
}
render() {
return (<div>
<input value={this.state.paramA} onChange={e => this.handleChange.bind(this)(e)}/>
<label>
<B paramA={this.state.paramA} />
</label>
</div>);
}
};
ReactDOM.render(
<App />,
document.getElementById('container')
);
<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>
<div id="container"></div>
Upvotes: 1
Reputation: 6427
It sounds like you're looking for the shouldComponentUpdate
lifecycle hook.
Pretty self explanatory; if the component should only re-render under specific prop/state changes, you can specify those in this hook, and return false otherwise.
Upvotes: 1