所以这是我的状态:
this.state = {
ids: ['A', 'E', 'C']
};
我将如何修改状态以便' E'在索引1处更改为' B&#39 ;? 例如:
this.setState({
ids[1]: 'B'
});
如何做到这一点?
答案 0 :(得分:22)
我的建议是习惯使用不可变操作,因此不要修改内部状态对象。
正如react docs:
所指出的那样不要直接改变this.state,因为之后调用setState()可能 替换你所做的突变。 将此状态视为好处 不可变的。强>
在这种情况下,您可以 [1] 使用slice()
来获取数组的新副本, [2] 操纵副本,然后使用新数组 [3] setState。这是一个很好的实践。
类似的东西:
const newIds = this.state.ids.slice() //copy the array
newIds[1] = 'B' //execute the manipulations
this.setState({ids: newIds}) //set the new state
答案 1 :(得分:13)
案例1:如果您知道索引,那么您可以这样写:
let ids = [...this.state.ids]; // create the copy of state array
ids[index] = 'k'; //new value
this.setState({ ids }); //update the value
案例2 :如果您不知道索引,那么首先使用array.findIndex或任何其他循环来获取您要更新的项目的索引,在更新之后value并使用setState。
像这样:
let ids = [...this.state.ids];
let index = ids.findIndex(el => /* condition */);
ids[index] = 'k';
this.setState({ ids });
答案 2 :(得分:0)
基于@ mayank-shukla所写的内容(案例2:知道要替换的项目的索引),这也可以用Array.splice编写:
const replacement = 'B';
let copy = [...this.state.ids]
copy.splice(index, 1, replacement)
this.setState({
ids: copy,
})
有两点需要注意:
Array.splice
是变异的;它将改变它操作的数组,但由于扩展运算符,这是数组的浅表副本。更多关于以下内容。 Array.splice
的返回值实际上是已删除的元素。 又说明:不要将切片的结果分配给您要分配给setState
中的ID的变量,否则最终只会删除已删除的值。 要跟进第1项中的浅层和深层副本,请注意,如果要替换对象引用(vs问题中的字符串文字),则需要使用lodash's cloneDeep之类的内容。
虽然有handful of other ways around this。
您还可以在SO itself上阅读有关浅与深的更多信息。
答案 3 :(得分:0)
这是在setState中更改数组的特定索引的另一种解决方案:
this.setState({
...array,
Object.assign([...array], { [id]: yourNewObjectOrValue })
})
答案 4 :(得分:0)
this.setState({
ids: [ids[1]='B',...ids].slice(1)
});
上面的代码将创建两个值为 'B' 的数组项,
一个在开始,一个在指定位置。
只需使用切片运算符删除第一个数组元素。
另一种解决方案是直接使用拼接运算符来完成
this.setState({
ids: [ids.splice(1,1,'B')]
})
答案 5 :(得分:0)
我意识到这个问题很老了,但今天有一个更好的答案。
immer 可用于支持使用熟悉的 API 以更明智的方式更改不可变对象。通过将函数传递给 this.setState
,您可以使用它来转换您的状态。
this.setState(state => produce(state, state => {
state.ids[1] = 'b'
}));
或者,如果您更喜欢柯里化,produce(fn)
是创建一个函数的有用快捷方式,该函数接受一个参数并将其转发到您的转换中:
this.setState(produce(state => {
state.ids[1] = 'b'
}));
我发现当涉及深层状态更改时,Immer 很棒,但请注意,它不是免费的。