React:当state是一个对象数组时更新状态

时间:2016-06-06 16:40:47

标签: reactjs ecmascript-6

我有一个处于状态的对象数组:

this.state = {
  items: [
    {id: 1, someattr: "a string", anotherattr: ""},
    {id: 2, someattr: "another string", anotherattr: ""},
    {id: 3, someattr: "a string", anotherattr: ""},
  ]
}

我需要能够根据id属性搜索items数组,然后更新对象属性。

我可以使用id参数在数组上通过filteringfinding获取对象。

我遇到的问题是更新阵列,然后更新状态而不会发生变异。

//make sure we're not mutating state directly by using object assign
const items = Object.assign({}, this.state.items);
const match = items.find((item) => item.id === id);

此时我有一个匹配的对象,可以使用对象扩展来更新它的属性:

const matchUpdated = { ...match, someattr: 'a new value'};

我的问题是如何用matchUpdated更新状态,以便覆盖初始查找操作返回的对象?

5 个答案:

答案 0 :(得分:22)

您的更新功能如下所示

updateItem(id, itemAttributes) {
  var index = this.state.items.findIndex(x=> x.id === id);
  if (index === -1)
    // handle error
  else
    this.setState({
      items: [
         ...this.state.items.slice(0,index),
         Object.assign({}, this.state.items[index], itemAttributes),
         ...this.state.items.slice(index+1)
      ]
    });
}

你就像这样使用它

this.updateItem(2, {someattr: 'a new value'});

总权利?

但是,如果你继续以这种方式构建复杂的应用程序,那么你将会遇到很大的麻烦。您应该真正研究redux或其他更适合解决这些问题的Flux实现。

Redux使用状态缩减器的概念,每个状态缩减器都在应用程序状态的特定片上工作。这样,每次想要影响深层次变化时,您都不必手动挖掘整个状态。

Redux的创作者Dan Abramov已经免费在线提供了两个视频课程。 Dan是一位优秀的老师,在我花了一个下午之后,我对Redux模式感到很自在。

答案 1 :(得分:2)

如果您想使用一个函数,这就是我的方法...

ConceptName auto

函数的第一个输入是项目的ID。

函数的第二个输入是您想要更改的属性。

函数的第三个输入是该属性的新值。

答案 2 :(得分:1)

如果你使用函数式组件和 useState 钩子,你可以很容易地使用 map,只要你不介意替换整个对象

const [items, setItems] = useState ([
    {id: 1, someattr: "a string", anotherattr: ""},
    {id: 2, someattr: "another string", anotherattr: ""},
    {id: 3, someattr: "a string", anotherattr: ""},
])

setItems (
    items.map((item) => {
        item.id === updatedItem.id? updatedItem: item;
    })
); 

答案 3 :(得分:0)

您可以遍历状态数组对象的值并替换状态。 在循环中,如果不是全部,您可以决定要应用新值的记录。

this.state = {
  items: [
    {id: 1, someattr: "a string", anotherattr: ""},
    {id: 2, someattr: "another string", anotherattr: ""},
    {id: 3, someattr: "a string", anotherattr: ""},
  ]
}

//答案

const newState = Object.assign({}, this.state);
   
newState.items.forEach(element => {

  element.someattr= "I like it a lot";

});

this.setState(newState);

答案 4 :(得分:-2)

在这样的功能组件中 你必须把它添加到函数中

const [item,setitem]=usestate([{id_1:null},{id_2:null}])
()=> setitems((prev) => { return { ...prev, id_1: "my change value"} }) 

并像这样使用它

  console.log(items.id_1 == "my change value")