简体   繁体   中英

Updating state as a nested object

I have this type of state in my app

state = {
  abc: true,
  array: [
    { id: 12345, done: false },
    { id: 10203, done: false },
    { id: 54321, done: false }
  ]
}; 

I am looking for a solution to the following problem: I need to change done property accordingly to passed id like in the following function when something like this handle(12345) is passed as an argument to handle function :

  handle = id => {
  this.state.array.map(e => {
    if (e.key === id) {
      this.setState({array: [
        { id: id, done: true },
        { id: 10203, done: false },
        { id: 54321, done: false }
      ]})
    }
  });
};

In simple words I need to change just one object in array based on provided id.

Thanks for any help or tips!

I'd write the handle method as:

handle = id => {
  this.setState(prevState => {
    const { array } = prevState;
    return {
      array: [
        ...array.filter(o => o.id !== id),
        {id, done: true}
      ]
    };
  });
};

The idea here is that, remove the matching id from old state, and then add a new object to the array with id and done property as {id, done: true} .

Once you are allowed to restructure state to be hashmap instead of array:

state = {
  abc: true,
  array: {
    12345: { done: false },
    10203: { done: false },
    54321: { done: false }
  ]
}; 

then you will be able to use power of spread operator:

let id = 12345;
this.setState({
    array: {
        ...this.state.array,
        [id]: {
            ...this.state.array[id], 
            done: true
        }
    }
});

Otherwise using array.map() seems to be the only option

You can use this Redux pattern to return a new array with the element in question being changed, while keeping your array immutable:

handle = id => {
  const updatedArray = this.state.array.map(e => {
    if (e.key === id) {
      return { id: id, done: true };
    }
    else {
      return e;
    }
  });
  this.setState({array: updatedArray});
};

This keeps your data structures immutable while changing only what you need to change.

var newArray = this.state.array;
  for(var i = 0; i < newArray.length; i++){
      if(newArray[i].id === 12345) {
        newArray[i].done = true;
      }
  }

  this.setState({array: newArray});

By creating the newArray here you will be avoiding directly touching the state element, so you can change anything you want inside it afterwards you can set the state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM