简体   繁体   English

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

[英]How to change useState for nested array of objects

I have a state:我有一个状态:

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")

Now I want to update school for the id:d1 inside id:2.现在我想为 id:2 中的 id:d1 更新学校。 Suppose the old value is school: xyz123 now I want to update it to school: newxyz123.假设旧值为 school: xyz123 现在我想将其更新为 school: newxyz123。 How can I achieve this using the spread operator or by another method?如何使用扩展运算符或其他方法实现此目的?

I tried the below code:我尝试了以下代码:

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; }););

But I am getting this as an ouput: { id:"c1", name: "ghi", school: "newxyz123" }但我将其作为输出:{ id:"c1", name: "ghi", school: "newxyz123" }

I suggest creating a function that receives the original array, a matcher function, and a replace function.我建议创建一个接收原始数组的函数、一个匹配器函数和一个替换函数。 The purpose of this function is to return a new array with the value changed.这个函数的目的是返回一个值改变的新数组。

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;
    });
}

Then, use the function to replace the values.然后,使用该函数替换这些值。

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 }
});

What this will do:这会做什么:

  1. Using the original array, find the object where the id (in the root object) is "2".使用原始数组,找到 id(在根对象中)为“2”的对象。
  2. Apply the replacer function, which will:应用替换函数,它将:
    1. Use the obj_of_names to find the object where the id is "d1".使用obj_of_names查找 id 为“d1”的对象。
    2. Apply the replacer function to return a new object with the new school value, using the spread operator.使用扩展运算符应用替换函数以返回具有新学校值的新对象。
    3. Return a new object cloned by the spread operator with replaced obj_of_names object, which contains the replaced school value.返回一个由扩展运算符克隆的带有替换的obj_of_names对象的新对象,其中包含替换的学校值。

Of course, you can improve this code and its readability by using various libraries to clone the objects, mutate them, and return new objects, but it is a workaround if you want to get started.当然,您可以通过使用各种库来克隆对象、对其进行变异并返回新对象来改进此代码及其可读性,但如果您想开始,这是一种解决方法。 Also, if you want to change the school name, I suggest using the answer @aweimon referenced, but if you want to change multiple objects on various criteria, you can improve the function above.另外,如果您想更改学校名称,我建议使用@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" }]
             }]

You can call a map inside another map and change the array whitin the object like so:您可以在另一个地图中调用地图并更改对象中的数组,如下所示:

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)

Then you can call setState and update it with the newArr然后你可以调用setState并用newArr更新它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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