netchicken
netchicken

Reputation: 485

React Updating Nested State Object deletes other values

I have read and tried many other variations of this issue from here but none seem to work.When I update the nested login object below using the DropDown it clears out all the other values entered into the Login object. As a result you have to run the dropdown first, then enter the other values in. This is not a good solution.

this.state = {
  login: {
    id: 0,
    firstName: "",
    lastName: "",
    business: "",
    dateIn: 0,
    dateOut: 0,
    staffName: ""
  },
  dropdownOpen: false,
  saveVisitor: false,
  dropDownValue: "",
  inputBoxEnabled: false
};

Here is my method.

//passes the value from the dropdownbox to the staffNames property
changeDropDownValue(e) {
  const newValue = e.currentTarget.textContent; // e.target.value;

  //The idea is to create a dummy object perform operations on it and then replace the component's state with the updated object
  //https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react

  var login = { ... this.state.login }
  login.staffName = newValue;
  this.setState({login})

  this.setState({
    ...this.state,
    inputBoxEnabled: true,
    dropDownValue: newValue
  });
}

Anyone got an answer? Nested objects seem to be very problematic, but necessary when you sending the data to a db.

Upvotes: 1

Views: 83

Answers (2)

JeromeBu
JeromeBu

Reputation: 1159

You should not do twice this.setState in a row like this, because setState is asynchronous. this.state value in the second is not yet updated.

instead try :

var login = { ... this.state.login, staffName: newValue }

this.setState({
  ...this.state,
  login,
  inputBoxEnabled: true,
  dropDownValue: newValue
});

Upvotes: 2

ggovan
ggovan

Reputation: 1927

You are making two calls to setState and in the second one you pass the current state (but modified). setState updates the state asynchronously, the value of state in the second setState call does not have the new login values, and will be applied after the updated login values. This makes your changes in the first call to setState get lost.

Either:

  • make a single call to setState
  • only update explicitly the fields that have to change

You could also consider using useState from react hooks and segregate your state with those.

Upvotes: 1

Related Questions