JoShin
JoShin

Reputation: 71

avoid child component re-render when state element is object

child component state like:

interface State {
    data: { x: number; y: string };
}

// initial in constructor
this.state = {
     data: {
         x: 10,
         y: 'sss',
     },
};

when do setState like:

const { data } = this.state;
data.x += 10;
this.setState({ data });

nextState always equal this.state in shouldComponentUpdate, console log in shouldComponentUpdate is:

next: {"data":{"x":20,"y":"sss"}} 
this: {"data":{"x":20,"y":"sss"}}

I want to render child component only when child after setState, instead of parent component render.

so, when parent component render, how to avoid child re-render

here is codesandbox


update:

find an answer, how to set nested state object:

Upvotes: 1

Views: 58

Answers (1)

Dennis Vash
Dennis Vash

Reputation: 53894

The problem is that you mutating the current state and then comparing it with the next state.

export default class App extends React.Component {
  state = {
    name: 'hello',
    data: {
      x: 10,
      y: 'sss'
    }
  };

  shouldComponentUpdate(nextProps, nextState) {
    console.log('this', this.state.data.x);
    console.log('next', nextState.data.x);
    const isRender = this.state.data.x !== nextState.data.x; 
    console.log('will render?', isRender);
    return isRender;
  }

  render() {
    const { name, data } = this.state;
    // Dont mutate state
    // data.x += 10;
    return (
      <FlexBox>
        <Input
          value={name}
          onChange={e => this.setState({ name: e.target.value, data: data.x+10 })}
        />
      </FlexBox>
    );
  }
}

Edit Q-57818273-MutateState


In your sandbox example, fix shouldComponentUpdate logic:

  shouldComponentUpdate(nextProps, nextState) {
    console.log('In should child update', nextState.data, this.state.data);
    const willRender = nextState.data !== this.state.data;
    console.log('will render?', willRender);
    return willRender;
  }

  changeCurrentState = () => {
    const { data } = this.state;

    // Dont mutate state.
    // data.x += 10;
    // this.setState({ data });
    this.setState({ data: { x: data.x + 10 } });
  };

Edit Q-57818273-ChildNotRenderOnParent

Upvotes: 1

Related Questions