Estoy tratando de agregar un elemento en un índice específico dentro de una matriz dentro de una función de mapa y se ha comportado de manera inesperada. Aquí está el código para ello
const addItemToLevelTwoArray= (uniqueID, arrayID )=> { const reportObject = { id:arrayID, title:'', } data.map(section=>{ section.content.map((report, reportIndex)=>{ if(report.id===uniqueID){ section.content.splice(reportIndex, 0, reportObject); } return report; }) return section; }) }Aquí hay un bolígrafo que funciona: https://codepen.io/raufabr/pen/vYZYgOV?editors=0011
El comportamiento esperado es que insertaría un objeto en el índice específico, justo encima del objeto donde coincide la ID.
Sin embargo, está actuando de manera extraña y, a veces, se agregan 2 elementos en lugar de uno.
¡Cualquier consejo sobre lo que estoy haciendo sería enormemente apreciado! ¡Sé que estoy cerca, pero he estado atascado en esto por un tiempo y no puedo entender qué estoy haciendo mal!
Puedes usar flatMap :
const data = [ { content: [ { id: 1, title: "a" },{ id: 3, title: "c" }, ] } ] const addItemToLevelTwoArray= (uniqueID, arrayID )=> { const reportObject = { id:arrayID, title:'', } return data.map(section=> { return { ...section, content: section.content.flatMap( report => report.id === uniqueID ? [reportObject, report] : report ) } } ) } console.log(addItemToLevelTwoArray(3, 2))Prefacio: Estás usando el map incorrectamente. Si no está utilizando la matriz que crea y devuelve el map , no hay motivo para utilizarla; solo usa un bucle o forEach . Más en mi publicación aquí . Y una de las razones para usar un bucle for antiguo es que tienes el control de la iteración, lo cual es importante porque...
Sin embargo, está actuando de manera extraña y, a veces, se agregan 2 elementos en lugar de uno.
Esto se debe a que está insertando en la matriz que el map está haciendo un bucle, por lo que en el siguiente paso, recoge la entrada que está agregando.
Si hace un bucle simple, puede evitarlo fácilmente incrementando el índice cuando inserte, o haciendo un bucle hacia atrás; aquí está el enfoque de bucle hacia atrás:
const addItemToLevelTwoArray = (uniqueID, arrayID) => { const reportObject = { id: arrayID, title: "", }; for (const section of data) { for (let reportIndex = section.content.length - 1; reportIndex >= 0; --reportIndex) { const report = section.content[reportIndex]; if (report.id === uniqueID) { section.content.splice(reportIndex, 0, reportObject); } } } };Debido a que estamos retrocediendo, no recuperaremos la entrada que acabamos de agregar en el siguiente paso.
Dado que el bucle externo no tiene ese problema, utilicé el for-of más conveniente.
Dado que preguntó sobre map , si usa los retornos del map de matriz, puede hacerlo devolviendo una matriz con las dos entradas y luego llamando flat en las compilaciones del map de matriz. (Esto solo funciona si la matriz aún no contiene matrices, porque se aplanarán). Esto es lo suficientemente común como para combinarlo en una función: flatMap . No es lo que yo haría (haría un ciclo), pero ciertamente es factible. Seguir con forEach y flatMap en lugar de usar for-of y for :
const addItemToLevelTwoArray = (uniqueID, arrayID) => { const reportObject = { id: arrayID, title: "", } data.forEach(section => { section.content = section.content.flatMap(report => { if (report.id === uniqueID) { // Return the new one and the old one return [reportObject, report]; } // Return just the old one return report; }); }); }; Eso supone que está bien modificar el objeto de la section . Si no es así, la respuesta de Alberto Sinigaglia muestra la creación de un nuevo objeto de reemplazo, lo cual es útil en algunas situaciones.
Lo siguiente extenderá el contenido de la matriz .content sin modificar los data la matriz original:
const data = [ {id: 0,title:'main',content:[{id:1,title:'Hello'}, {id:2,title:"World"}] } ]; const addItemToLevelTwoArray= (uniqueID, arrayID )=> { const reportObject = { id:arrayID, title:'something new!', } return data.map(d=>( {...d, content:d.content.reduce((acc, rep)=>{ if(rep.id===uniqueID) acc.push(reportObject); acc.push(rep) return acc; },[]) // end of .reduce() })); // end of .map() } const res=addItemToLevelTwoArray(1,123); console.log(res);