7

I'm trying to update the state, based on previous state (array of objects) with the new incoming values in fase of object. But for some reasons it does not happen...

What is I'm doing wrong? My code:

   handleCommentSubmit = (newEmployer) => {
       console.log('handleCommentSubmit BEFORE', this.state.employers, newEmployer); // array(5)
       this.setState((prevState, newEmployer) => { 
         employers: prevState.employers + newEmployer
       });
       console.log('handleCommentSubmit AFTER', this.state.employers); // still array(5)
   }

My log:

handleCommentSubmit BEFORE (6) [{…}, {…}, {…}, {…}, {…}, {…}], newEmployer: {first_name: "sdfsdf", last_name: "sdfsdf", birth_date: "123123-03-12", salary: "123123123"}
handleCommentSubmit AFTER (6) [{…}, {…}, {…}, {…}, {…}, {…}]
Alex Antonov
  • 14,134
  • 7
  • 65
  • 142
Max Wolfen
  • 1,923
  • 6
  • 24
  • 42

4 Answers4

9

Changes:

1- setState is async so use callback to check the updated value.

2- Use [].concat to push a new value in array, + will not work.

3- You are not returning the object from the updater function.

Write it like this:

handleCommentSubmit = (newEmployer) => {
    this.setState((prevState, newEmployer) => ({
        employers: prevState.employers.concat(newEmployer)
    }), () => {
        console.log('handleCommentSubmit AFTER', this.state.employers);
    }); 
}

Check this answer for more details:

Why calling setState method doesn't mutate the state immediately?

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • 1
    See React's page : https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous To further enhance the relevance of @Mayank's solution. – aneth101 Jan 29 '20 at 16:37
3

If your employers is an Array you can use spread operator in setState:

[...prevState.employers, newEmployer]

but you don't need prevState at all. You can just:

this.setState({ 
         employers: [...this.state.employers, newEmployer]
       });
Arkej
  • 2,221
  • 1
  • 14
  • 21
2

if you call the setState it won't update immediately in the next line. It will update after the render method gets called. If you want to see the updatedState you can write a callback function in the setState like this.

this.setState((prevState, newEmployer) => { 
         employers: prevState.employers + newEmployer
       }, () => console.log('UpdatedState', this.state.employers));
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Trinu
  • 1,721
  • 3
  • 21
  • 41
-7

this.setState should receive object as an argument. Not a function. You could easily use this.state:

handleCommentSubmit = (newEmployer) => {
  this.setState({ 
    employers: this.state.employers.concat(newEmployer)
  });
}
Alex Antonov
  • 14,134
  • 7
  • 65
  • 142
  • 2
    -1. `this.setState` *does* accept a function as an argument, see [docs](https://reactjs.org/docs/react-component.html#setstate). – Sumit Aug 13 '18 at 12:52
  • setting state may be asychroneous, this solution has a chance to cause problems in certain cases. View my solution with explanation below. – aneth101 Jan 29 '20 at 16:34
  • 1
    This answer is wrong. It is advised to use the function parameter to update state when the new state depends on the previous state--given the asynchronous nature of `setState`. – Doug Feb 08 '20 at 01:34
  • Please don't provide wrong information if you are not sure about it. setState accepts both object as well as function, it depends on your usage what you want to use at the moment. – Hackytech Nov 08 '22 at 06:14