Estoy tratando de manipular una matriz como esta:
data = [ { "id":"1", "items":[ { "title":"item 1" }, { "title":"item 2" } ] }, { "id":"2", "items":[ { "title":"item2 1" }, { "title":"item2 2" } ] } ]Necesito, por ejemplo, empujar otra matriz:
[ { "title":"item new 1" }, { "title":"item new 2" } ]inside data[0].items y obtener:
data = [ { "id":"1", "items":[ { "title":"item new 1" }, { "title":"item new 2" } ] }, { "id":"2", "items":[ { "title":"item2 1" }, { "title":"item2 2" } ] } ]... ¿cómo puedo hacer esto manteniendo la inmutabilidad , por ejemplo con Lodash ? No entender y saber cómo cambiar solo un subobjeto específico en una estructura de datos. ¿Alguien tiene sugerencias?
Gracias
A continuación, se presenta una forma posible de agregar de forma inmutable una matriz determinada a un accesorio de "items" de índice particular.
Fragmento de código
const immutableAdd = (aIdx, addThis, orig) => { const newData = structuredClone(orig); newData[aIdx].items = addThis; return newData; }; const data = [{ "id": "1", "items": [{ "title": "item 1" }, { "title": "item 2" } ] }, { "id": "2", "items": [{ "title": "item2 1" }, { "title": "item2 2" } ] } ]; const addThisArr = [{ "title": "item new 1" }, { "title": "item new 2" } ]; console.log('immutableAdd result: ', immutableAdd(0, addThisArr, data)); console.log('original data: ', data); .as-console-wrapper { max-height: 100% !important; top: 0 }Explicación
structuredClone() para realizar una clonación profunda de la matriz data existente.aIdx de la matriz clonadaitems de aIdx .NOTA
Esta solución no usa lodash ya que no es obligatorio (usar lodash ) para realizar operaciones inmutables.
Si desea mantener la inmutabilidad de los datos originales, simplemente asigne el contenido de los datos originales a los datos nuevos como desee y ajuste su lógica en una función pura para mejorar la legibilidad.
const dataOriginal = [{ "id": "1", "items": [{ "title": "item 1" }, { "title": "item 2" } ] }, { "id": "2", "items": [{ "title": "item2 1" }, { "title": "item2 2" } ] } ] const dataNew = createDataWithSomethingNew(dataOriginal, [{ "title": "item new 1" }, { "title": "item new 2" } ]) function createDataWithSomethingNew(data, props) { return data.map(function changeItemsOfId1ToProps(value) { if (value.id === '1') { return { id: value.id, items: props } } else { return value } }) }lodash tiene un método _.update puede modificar el objeto con la path correcta en la cadena proporcionada.
Otro método _.cloneDeep puede copiar su objeto profundamente. De modo que ese cambio en el objeto precopiado no afectará al objeto clonado.
Finalmente, use una función de congelación profunda para llamar a Object.freeze recursivamente en el objeto clonado para hacerlo inmutable .
var data = [ { "id":"1", "items":[ { "title":"item 1" }, { "title":"item 2" } ] }, { "id":"2", "items":[ { "title":"item2 1" }, { "title":"item2 2" } ] } ] var clonedData = _.cloneDeep(data) // copy the full object to avoid modify the source data // update the data of that path '[0].items' in clonedData _.update(clonedData, '[0].items', function(n) { return [ { "title":"item new 1" }, { "title":"item new 2" } ] }) // provide object immutability const deepFreeze = (obj1) => { _.keys(obj1).forEach((property) => { if ( typeof obj1[property] === "object" && !Object.isFrozen(obj1[property]) ) deepFreeze(obj1[property]) }); Object.freeze(obj1) }; deepFreeze(clonedData) data[2] = {id: 3} // data will be changed data[1].items[2] = {title: "3"} // and also this one clonedData[2] = {id: 3} // nothing will be changed clonedData[1].items[2] = {title: "3"} // and also this one console.log(`data:`, data); console.log(`clonedData:`, clonedData);