1

I'm having a heck of time with this. I do NOT want my child to re-render when the parents state changes. I've tried to use shouldComponentUpdate in the child component, but for some reason that's not even being invoked.

My issue is this. I have several charts on a grid, I want to update one of the charts configuration settings, which I pass as a prop to the component. The parent, which they all share, updates that childs config, but in the process, the config changes and thus they all re-render.

Why isn't shouldComponentUpdate being invoked? It gets invoked on the parent, so I'm assuming it is invoked where the state changes???

My code looks something like:

Parent - has selectDataType with setState Child1 - calls selectDataType which was passed down as a prop, which re-renders Child2 - no changes to it's props, but re-renders, which I need to stop

Parent:

selectDataType(e) {
    e.stopPropagation();

    var cellId = e.currentTarget.dataset.id;
    var cellValue = e.currentTarget.childNodes[0].value;

    var newCells = [];

    newCells = this.state.cells.map(function (cell, i) {
        var newObj = Object.assign({}, cell);

        if (cellId == cell.id) {
            newObj['dataType'] = cellValue;
        }

        return newObj;
    });

    this.setState({
        cells: newCells
    });

    return;
}

Child1:

export default class Pie extends React.Component {
    constructor(props) {
    super(props);

    this.create = this.create.bind(this);
}

shouldComponentUpdate() {
    return false;
}

create() {
    return {
        //some data
    }
}

render() {
    return (
        <div>
            <ReactECharts
                option={ this.create() }
                style={{ position: "absolute", top: 0, bottom: 0, left: 0, right: 0, height: "100%" }}
                theme="chalk"
                notMerge={ true }
            />
        </div>
    )
}

}

Child2: exactly like Child1

stevenlacerda
  • 1,187
  • 2
  • 9
  • 21
  • shouldComponentUpdate() : [Returning false does not prevent child components from re-rendering when their state changes.](https://reactjs.org/docs/react-component.html#shouldcomponentupdate) – dave May 08 '18 at 22:23
  • How do you render the children in the parent? A possible reason is not giving a static `key` property to the child components. If they're given, say, a random key every time they're rendered, then they'll completely unmount and remount with its new parent properties. So the child component isn't updating, it's remounting. Hence `shouldComponentUpdate` won't be called – Jayce444 May 08 '18 at 22:26
  • Can you show us the parent's render? – Leandro Soares May 08 '18 at 22:32
  • ahhhh...@Jayce444 that seems reasonable. Let me check it out and get back to you. – stevenlacerda May 08 '18 at 22:38
  • @Jayce444 You're a rockstar :) That did the trick, was using a random key. Thanks for the help. If you want to add that as your answer, I'll upvote and close as answered. – stevenlacerda May 08 '18 at 23:09
  • Alrighty, posted – Jayce444 May 09 '18 at 01:24
  • 1
    Thanks @Jayce444. It solved my problem too. Been pulling my hair out on this one. – snowykz Jun 03 '21 at 09:53

2 Answers2

7

Make sure your children are given a static key prop (as for all arrays of components). If they're given a random key, then when the parent re-renders it'll give all the children a new random key (different from their old one). This will make React think it's a completely different component, so the existing one will completely unmount and be remounted (with the new properties). So the child component isn't updating, it's remounting. Hence shouldComponentUpdate won't be called.

Jayce444
  • 8,725
  • 3
  • 27
  • 43
0

You might find answers here, for both classes and hooks: ReactJS: setState on parent inside child component

Short answer for hooks would be:

  • Send parent state and setState in child prop. Lets call those parentState and setParentState
  • In child component:
    • have a useEffect which only does something when parentState is updated:
    useEffect(() => {
        props.parentStateSetter(childStateValueYouWantToTrack);
    }, [props.parentState, childStateValueYouWantToTrack]);

You should check out the link for more information

Quev
  • 41
  • 2