0
votes

I've got a component, which has its props set by the parent component. The parent component changes regularly but the props of the child don't.

For some reason however the child keep rendering but I can't figure out why. To verify that the props and state are not changing I've added this function:

shouldComponentUpdate(nextProps, nextState) {
    console.info(JSON.stringify(nextProps)+JSON.stringify(nextState));

    console.info('NEXT PROPS ====================');
    for (var n in nextProps) {
        if (!nextProps.hasOwnProperty(n)) continue;
        console.info(n + ' = ' + (nextProps[n] === this.props[n]));
    }

    console.info('NEXT STATE ====================');
    for (var n in nextState) {
        if (!nextState.hasOwnProperty(n)) continue;
        console.info(n + ' = ' + (nextState[n] === this.state[n]));
    }

    return true;
}

This will print the following in the console:

{"autocomplete":null,"value":"","theme":1,"style":{"width":1426,"height":783},"label":"","description":null,"visible":false,"buttons":null,"inputType":null}{"visible":false,"answer":""}
NEXT PROPS ====================
autocomplete = true
value = true
theme = true
style = true
onClose = true
label = true
description = true
visible = true
buttons = true
inputType = true
NEXT STATE ====================
visible = true
answer = true

{"autocomplete":null,"value":"","theme":1,"style":{"width":1426,"height":783},"label":"","description":null,"visible":false,"buttons":null,"inputType":null}{"visible":false,"answer":""}
NEXT PROPS ====================
autocomplete = true
value = true
theme = true
style = true
onClose = true
label = true
description = true
visible = true
buttons = true
inputType = true
NEXT STATE ====================
visible = true
answer = true

So from one call to the next the state and props are strictly equal, yet the render() function of this component keep being called. Note that this shouldComponentUpdate() is just for testing - if I remove it, render() also keep being called under the same conditions.

Any idea what could be causing this?

1
The child component also rerender if the parent component is updated even if the prop of child component remain the same. If you want to avoid rerendering of child then simply return false from shouldComponentUpdate method.Prakash Sharma

1 Answers

4
votes

I've got a component, which has its props set by the parent component. The parent component changes regularly but the props of the child don't. For some reason however the child keep rendering but I can't figure out why.

The child keeps re-rendering because it is inside of the Parent's render method - which as you mentioned keeps changing.

To better see why the child gets invoked, remember that JSX get transformed back into regular JS, so something like:

render() {
  return (
    ...
    <ChildComponent someProp={"hello"} />
    ...
  );
}

Becomes:

render() {
  return React.createElement(
    ...,
    React.createElement(ChildComponent, { someProp: "hello" }),
    ...
  );
}

If you don't want the child to get re-rendered you should do a check to see if its props did not change and return false inside of shouldComponentUpdate or extend from React.PureComponent which takes care of that for you automatically - see the difference.

Also note that re-rendering !== re-drawing, just causes React's diffing algorithm to run, and only, if the diffing algorithm sees a difference in the current version of the virtual DOM compared to the previous version of the virtual DOM will the specific "changed" part of the UI get re-drawn on the screen.