如何更改嵌套数组对象的useState



我有一个状态:

const obj = [{id: "1", obj_of_names: [{
id: "a1",
name: "abc",
school: "xyz" },
{ id:"b1",
name: "def",
school: "zyx" },
{ id:"c1",
name: "ghi",
school: "pqr" }]
},
{id: "2", obj_of_names: [{
id: "d1",
name: "abc123",
school: "xyz123" }]
}]
const [newobj, setObj] = useState("obj")

现在我想为id:2里面的id:d1更新school。假设旧值是school: xyz123,现在我想将其更新为school: newxyz123。如何使用扩展运算符或其他方法实现这一点?

我尝试了下面的代码:

setObj((prevObjects) => {
const tempIndex = prevObjects.findIndex(
(item) => item.id === reqdImgID
);
const newObject = obj[tempIndex].obj_of_names.map((obj) => { 
if (obj.id == reqdID) { 
return {  ...obj, 
school: newSchool,};}
return obj; }););

但我得到这个作为输出:{id:"c1",名称:"ghi",学校:"newxyz123"}

我建议创建一个接收原始数组的函数、一个匹配器函数和一个替换函数。此函数的目的是返回一个值已更改的新数组。

function mutateObject(array, matcher, replacer) {
// returns a new array, with all elements untouched, except for those that match the matcher function, which are replaced with new objects created by the replacer function
return array.map(function (item) {
return matcher(item) ? {...replacer(item)} : item;
});
}

然后,使用函数替换值

mutateObject(obj, group => group.id == "2", group => {
const newNames = mutateObject(group.obj_of_names, name => name.id === "d1", name => ({ ...name, school: "newxyz123" }));
return { ...group, obj_of_names: newNames }
});

这将做什么:

  1. 使用原始数组,查找id(在根对象中)为"2"的对象
  2. 应用replacer函数,它将:
    1. 使用obj_of_names查找id为"d1"的对象
    2. 使用扩展操作符,应用replacer函数返回一个具有新学校值的新对象。
    3. 使用已替换的obj_of_names对象返回由扩展操作符克隆的新对象,该对象包含已替换的学校值。

当然,您可以通过使用各种库来克隆对象、改变它们并返回新对象来改进这段代码及其可读性,但是如果您想要开始,这是一种变通方法。另外,如果你想更改学校名称,我建议使用@aweimon参考的答案,但如果你想在各种标准上更改多个对象,你可以改进上面的功能。

const obj = [{
id: "1",
obj_of_names: [{
id: "a1",
name: "abc",
school: "xyz"
},
{
id: "b1",
name: "def",
school: "zyx"
},
{
id: "c1",
name: "ghi",
school: "pqr"
}
]
},
{
id: "2",
obj_of_names: [{
id: "d1",
name: "abc123",
school: "xyz123"
}]
}
]
function mutateObject(array, matcher, replacer) {
// returns a new array, with all elements untouched, except for those that match the matcher function, which are replaced with new objects created by the replacer function
return array.map(function(item) {
return matcher(item) ? { ...replacer(item)
} : item;
});
}
const updatedObj = mutateObject(obj, group => group.id == "2", group => {
const newNames = mutateObject(group.obj_of_names, name => name.id === "d1", name => ({ ...name,
school: "newxyz123"
}));
return { ...group,
obj_of_names: newNames
}
});
console.log(updatedObj);

const arr = [{id: "1", obj_of_names: [{
id: "a1",
name: "abc",
school: "xyz" },
{ id:"b1",
name: "def",
school: "zyx" },
{ id:"c1",
name: "ghi",
school: "pqr" }]
},
{id: "2", obj_of_names: [{
id: "d1",
name: "abc123",
school: "xyz123" }]
}]

可以在另一个map中调用一个map,并在对象中更改数组,如下所示:

const newArr =  arr.map((item)=>{
if(item.id == 2){
return {...item, obj_of_names: item.obj_of_names.map((item2)=>{

if(item2.id === 'd1'){
return {...item2, school: 'newxyz123'}
}

return item2
}) }
}

return item
})
const [state, setState] = useState(arr)

那么你可以调用setState并使用newArr更新它

最新更新