type reducer react props example actions reactjs state redux mutation

reactjs - reducer - redux map state to props



Reemplazar elemento de matriz con otro sin mutar el estado (3)

Así es como se ve el ejemplo de mi estado:

const INITIAL_STATE = { contents: [ {}, {}, {}, etc.. ], meta: {} }

Necesito poder y de alguna manera reemplazar un elemento dentro de la matriz de contenido sabiendo su índice, lo he intentado:

return { ...state, contents: [ ...state.contents[action.meta.index], { content_type: 7, content_body: { album_artwork_url: action.payload.data.album.images[1].url, preview_url: action.payload.data.preview_url, title: action.payload.data.name, subtitle: action.payload.data.artists[0].name, spotify_link: action.payload.data.external_urls.spotify } } ] }

donde action.meta.index es el índice del elemento de matriz que quiero reemplazar con otro objeto de contenido, pero creo que esto simplemente reemplaza toda la matriz por este único objeto que estoy pasando. También pensé en usar .splice() pero ¿eso simplemente mutaría la matriz?


Splice mute la matriz que necesita para usar Slice . Y también necesitas concat la pieza en rodajas.

return Object.assign({}, state, { contents: state.contents.slice(0,action.meta.index) .concat([{ content_type: 7, content_body: { album_artwork_url: action.payload.data.album.images[1].url, preview_url: action.payload.data.preview_url, title: action.payload.data.name, subtitle: action.payload.data.artists[0].name, spotify_link: action.payload.data.external_urls.spotify } }]) .concat(state.contents.slice(action.meta.index + 1)) }


Tenga en cuenta que Array.prototype.map() ( docs ) no muta la matriz original, por lo que proporciona otra opción:

const INITIAL_STATE = { contents: [ {}, {}, {}, etc.. ], meta: {} } // Assuming this action object design { type: MY_ACTION, data: { // new content to replace }, meta: { index: /* the array index in state */, } } function myReducer(state = INITIAL_STATE, action) { switch (action.type) { case MY_ACTION: return { ...state, // optional 2nd arg in callback is the array index contents: state.contents.map((content, index) => { if (index === action.meta.index) { return action.data } return content }) } } }


Solo para construir sobre la respuesta de @sapy, que es la correcta. Quería mostrarle otro ejemplo de cómo cambiar una propiedad de un objeto dentro de una matriz en Redux sin alterar el estado.

Tenía una variedad de orders en mi estado. Cada order es un objeto que contiene muchas propiedades y valores. Sin embargo, solo quería cambiar la propiedad de la note . Entonces algo como esto

let orders = [order1_Obj, order2_obj, order3_obj, order4_obj];

donde por ejemplo order3_obj = {note: '''', total: 50.50, items: 4, deliverDate: ''07/26/2016''};

Entonces, en mi Reducer, tenía el siguiente código:

return Object.assign({}, state, { orders: state.orders.slice(0, action.index) .concat([{ ...state.orders[action.index], notes: action.notes }]) .concat(state.orders.slice(action.index + 1)) })

Entonces, esencialmente, estás haciendo lo siguiente:

1) Cortar la matriz antes de order3_obj así [order1_Obj, order2_obj]

2) Concat (es decir, agregue) el order3_obj editado utilizando el operador de tres puntos ... spread y la propiedad particular que desea cambiar (es decir, note )

3) Concat en el resto de la matriz de órdenes usando .concat y .slice al final .concat(state.orders.slice(action.index + 1)) que es todo después de order3_obj (en este caso order4_obj es el único que queda )