Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React. How to update the state with previous state?

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) [{…}, {…}, {…}, {…}, {…}, {…}]
like image 708
Max Wolfen Avatar asked Apr 12 '18 09:04

Max Wolfen


People also ask

Can you update state directly React?

React will then look at the virtual DOM, it also has a copy of the old virtual DOM, that is why we shouldn't update the state directly, so we can have two different object references in memory, we have the old virtual DOM as well as the new virtual DOM.

Why is React not updating on state change?

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.

How do you get a previous state in a functional component React?

With React class components you have the componentDidUpdate method which receives previous props and state as arguments or you can update an instance variable (this. previous = value) and reference it later to get the previous value.


3 Answers

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?

like image 111
Mayank Shukla Avatar answered Oct 23 '22 18:10

Mayank Shukla


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]
       });
like image 43
Arkej Avatar answered Oct 23 '22 19:10

Arkej


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));
like image 2
Trinu Avatar answered Oct 23 '22 17:10

Trinu