Search code examples
javascriptreactjsonclicksetstate

ReactJs - unable to update state with setState


I'm having trouble updating my state using setState.

I have a parent component where I define my state, as well as a handleClick function which should update the state.

export default class Main extends PureComponent {

  state = { 
    selectedName: '',
    selectedTasks: [],
    data: [
      { 
        name: 'John', 
        tasks: ['vacuum', 'cut grass']
      },
      { 
        name: 'Jack', 
        tasks: ['cook breakfast', 'clean patio']
      }
   ]

  handleClick = e => {
    console.log('Name: ', e.name);
    console.log('Tasks', this.state.data.find(el => el.name === e.name).tasks)
    const { selectedName, selectedTasks } = this.state;
    this.setState({
      selectedName: e.name
      selectedTasks: this.state.data.find(el => el.name === e.name).tasks
    });
    console.log('stateAfter', this.state)
  };

  render() {
    const { data } = this.state;
    return (
      <div>
        <Child
          data={data}
          handleClick={this.handleClick.bind(this)}
        />
      </div>
    )
  }
}

I have a child component that takes the handleClick as props.

export default class Child extends PureComponent {
  constructor(props) {
      super(props);
  }

  render() {
    console.log('data', this.props.data);
    return (
      <ResponsiveContainer width="100%" height={500}>
      <PieChart height={250}>
        <Pie
          data={this.props.data}
          onClick={this.props.handleClick}
        />
      </PieChart>
    </ResponsiveContainer>
    );
  }
}

When I execute the handleClick function the first time, nothing gets updated. But when I execute it the second time, the state does get updated. What am I missing to make state get updated the first time?


Solution

  • this.setState is asynchronous. If you wish to console.log your state after setState then you'll have to do this via the callback.

    this.setState({
       selectedName: e.name
       selectedTasks: this.state.data.find(el => el.name === e.name).tasks
    }, 
    () => {
       console.log('stateAfter', this.state)
    });