tengo un estado:
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")Ahora quiero actualizar la escuela para el id:d1 dentro del id:2. Supongamos que el valor anterior es la escuela: xyz123 ahora quiero actualizarlo a la escuela: newxyz123. ¿Cómo puedo lograr esto usando el operador de propagación o por otro método?
Probé el siguiente código:
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; }););Pero obtengo esto como salida: {id:"c1", nombre: "ghi", escuela: "newxyz123"}
Sugiero crear una función que reciba la matriz original, una función de comparación y una función de reemplazo. El propósito de esta función es devolver una nueva matriz con el valor cambiado.
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; }); }Luego, use la función para reemplazar los valores.
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 } });Qué hará esto:
obj_of_names para encontrar el objeto donde la identificación es "d1".obj_of_names reemplazado, que contiene el valor de la escuela reemplazada.Por supuesto, puede mejorar este código y su legibilidad mediante el uso de varias bibliotecas para clonar los objetos, mutarlos y devolver nuevos objetos, pero es una solución si desea comenzar. Además, si desea cambiar el nombre de la escuela, sugiero usar la respuesta a la que se hace referencia @aweimon, pero si desea cambiar varios objetos según varios criterios, puede mejorar la función anterior.
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" }] }]Puede llamar a un mapa dentro de otro mapa y cambiar la matriz dentro del objeto de esta manera:
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) Luego puede llamar a setState y actualizarlo con newArr