albert
albert

Reputation: 1348

React PureComponent is updating when it shouldn't be

I'm currently using, in my application, a PureComponent parent and children components. I expected a PureComponent to only update if it's state or props change. To ensure this, I had a child component log something everytime its componentDidUpdate() method was called. The application looks something like this:

class Parent extends React.PureComponent{
    constructor(props){
        super(props);

        this.state = {
            item1: null,
            item2: null,
            list1: [],
            list2: [],
        }

    render(){
        let combinedList= [...this.state.list1, ...this.state.list2];

        return(
            <React.Fragment>
                <Child myList={combinedList} />
                <OtherChild item={this.state.item1} />
            </React.Fragment>
        );

The Child component looks something like this:

class Child extends React.PureComponent{
    constructor(props){
        super(props);
    }

    componentDidUpdate(){
        console.log("Child updated");
    }

    render(){
        return(
            ....
        );
    }

For example, when the state of item2 in Parent component changes, the Child component will log "Child updated". I'm a bit confused, since the child component doesn't receive item1 as a prop, and it's state isn't changed. Is this happening because the Parent component rerenders all of it's children? Or maybe because the shallow comparison Child does for its myList prop indicate that it has changed? Aside from writing my own shouldComponentUpdate() method, how can I prevent Child from rerendering everytime Parent rerenders?

Upvotes: 2

Views: 1044

Answers (1)

LMulvey
LMulvey

Reputation: 1670

Right now, in your render function for the Parent component, you're creating a new Array on every render with combinedList. PureComponent switches your shouldComponentUpdate() method to do a shallow compare to see if it should update. Since it's shallow, it's comparing references.

Since you're creating a new array on every render, it's going to be new every single time the Parent renders.

The solution here really depends on the full use-case that you have for combinedList. Looking at this example directly, I would recommend that you set combinedList in state. The other option would be to split your child component props up into a list1 and list2 prop instead of a myList prop.

Upvotes: 5

Related Questions