remover - eliminar un elemento especifico de un array javascript
¿Cómo eliminar un objeto de una matriz en Immutable? (6)
Dado un estado como este:
state = {
things: [
{ id: ''a1'', name: ''thing 1'' },
{ id: ''a2'', name: ''thing 2'' },
],
};
¿Cómo puedo crear un nuevo estado donde se elimina la ID "a1"? Es bastante fácil empujar nuevos elementos:
return state.set(state.get(''things'').push(newThing));
Pero no puedo averiguar cómo buscar y eliminar un objeto por su propiedad id
. Intenté esto:
return state.set(''tracks'',
state.get(''tracks'').delete(
state.get(''tracks'').findIndex(x => x.get(''id'') === ''a2'')
)
)
Pero parece desordenado, y solo funciona si se encuentra el elemento, porque si findIndex
devuelve -1
, ese es un valor válido para delete
.
ImmutableJS trabajando con matrices anidadas
Immutablejs es excelente, pero al mismo tiempo complica las cosas en algunos casos, especialmente cuando se trabaja con matrices anidadas .
A veces es más fácil devolverlo a JS en un sentido general para este problema en particular.
// 1. get a copy of the list into normal JavaScript
const myList = state.getIn([''root'', ''someMap'', ''myList'']).toJS()
// 2. remove item in list using normal JavaScript and/or anything else
myList.splice(deleteIndex, 1)
// 3. return the new state based on mutated myList
return state
.mergeDeep({ root: { someMap: { myList: undefined } }})
.mergeDeep({ root: { someMap: { myList } }})
Desafortunadamente, el paso 3 es necesario para configurarlo específicamente como undefined
porque si simplemente configura myList
directamente como un valor de matriz, ImmutableJS hará una comparación de valores entre la lista actual y solo los modificará creando un comportamiento extraño.
La justificación para esto es simplificar la sobrecarga mental. No recomiendo hacer esto en un bucle, sino manipular la matriz JS pura en un bucle si debe hacerlo antes del paso 3.
Alternativamente, cuando esté "buscando y luego borrando" ...
var itemIndex = this.state.get("tracks").findIndex(x => x.get(''id'') === ''a2'');
return itemIndex > -1 ? this.state.deleteIn(["tracks", itemIndex]) : this.state;
Esto asegurará que el estado no se mute cuando no hay cambios.
Cuando está usando el filtro, itera todo el ciclo -> una forma efectiva es encontrar index => slice y usar splitter ...
const index = state.findIndex(data => data.id === action.id);
return [...state.slice(0, index), ...state.slice(index + 1)];
Encontré este hilo mientras buscaba una solución para una tarea similar. Resuelto con el método de update :
return state.update(''things'', (things) => things.filter((t) => t.id !== action.things.id))
¿Alguna idea / comentario cuál es mejor / preferido?
Puede utilizar Array#filter
.
return state.set(''things'', state.get(''things'').filter(o => o.get(''id'') !== ''a1''));
Puedes hacerlo incluso sin immutable.js con la siguiente función.
function arrayFilter(array, filter) {
let ret = array
let removed = 0
for (let index = 0; index < array.length; index++) {
const passed = filter(array[index], index, array)
if (!passed) {
ret = [...ret.slice(0, index - removed), ...ret.slice(index - removed + 1)]
removed++
}
}
return ret
}