ptriller ptriller - 5 days ago 6
React JSX Question

Why does React call the render method of an unchanged component?

I am curious about why React updates the Child Component in this case:

function Inner(props) {
console.log("Render Inner");
return <div>Inner</div>;
}

export class Outer extends React.Component {

constructor(props) {
super(props);
this.state = {
active: false
};
this.onClick = this.rawOnClick.bind(this);
}

render() {
console.log("Render Outer");
return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}><Inner/></div>;
}

rawOnClick(event) {
this.setState({ active: !this.state.active });
}
}


ReactDOM.render(<Outer/>, document.getElementById('app'));


When the component Outer is clicked, the render method of Inner and Outer are called. Since Components are supposed to be "pure" there is no need to call the render method of Inner, is there ? I can even make it that way, if I rewrite my code a little bit:

export function Inner(props) {
console.log("Render Inner");
return <div>Inner</div>;
}

export class Outer2 extends React.Component {

constructor(props) {
super(props);
this.state = {
active: false
};
this.onClick = this.rawOnClick.bind(this);
}

render() {
console.log("Render Outer");
return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}>{this.props.children}</div>;
}

rawOnClick(event) {
this.setState({ active: !this.state.active });
}
}

ReactDOM.render(<Outer2><Inner /></Outer2>, document.getElementById('app'));


Now only the render method of "Outer2" is called when I click the component. Is this intentional ? Is this a mission optimization, or do I miss something important.

Thanks.

Peter

Answer

That is the default behavior of React. You must override shouldComponentUpdate() in your Inner component to return true or false to determine if its own render() needs to be called again. That determination is usually made based upon the differences, if any, found between the current and next set of props and state.

In your example, where your Inner component always returns the same thing and is never affected by changes to props or state, you can just return false.

shouldComponentUpdate(nextProps, nextState) {
  return false;
};

(NOTE, you'll have to convert Inner from your stateless function to an ES6 class in order to use this lifecycle method.)

Read more at official docs - https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate

Comments