sort seamless react immutable delete javascript functional-programming immutable.js

javascript - seamless - ¿Cómo actualizar el elemento dentro de la Lista con ImmutableJS?



seamless immutable (7)

Esto es lo que dijeron los documentos oficiales

updateIn(keyPath: Array<any>, updater: (value: any) => any): List<T> updateIn(keyPath: Array<any>, notSetValue: any, updater: (value: any) => any): List<T> updateIn(keyPath: Iterable<any, any>, updater: (value: any) => any): List<T> updateIn(keyPath: Iterable<any, any>, notSetValue: any, updater: (value: any) => any): List<T>

¡No hay forma de que un desarrollador web normal (no un programador funcional) lo entienda!

Tengo un caso bastante simple (para un enfoque no funcional).

var arr = []; arr.push({id: 1, name: "first", count: 2}); arr.push({id: 2, name: "second", count: 1}); arr.push({id: 3, name: "third", count: 2}); arr.push({id: 4, name: "fourth", count: 1}); var list = Immutable.List.of(arr);

¿Cómo puedo actualizar la list donde el elemento con nombre tercero tiene su recuento establecido en 4 ?


updateIn es lo que dicen los documentos oficiales ... updateIn

No necesita updateIn , que es solo para estructuras anidadas. Está buscando el facebook.github.io/immutable-js/docs/#/List/update , que tiene una firma y documentación mucho más simple:

Devuelve una nueva Lista con un valor actualizado en el índice con el valor devuelto de llamar al actualizador con el valor existente, o notSetValue si no se estableció el índice.

update(index: number, updater: (value: T) => T): List<T> update(index: number, notSetValue: T, updater: (value: T) => T): List<T>

que, como sugieren los documentos de Map::update , es " equivalente a: list.set(index, updater(list.get(index, notSetValue))) ".

donde elemento con nombre "tercero"

Así no es como funcionan las listas. Debe conocer el índice del elemento que desea actualizar o debe buscarlo.

¿Cómo puedo actualizar la lista donde el elemento con nombre tercero tiene su recuento establecido en 4?

Esto debería hacerlo:

list = list.update(2, function(v) { return {id: v.id, name: v.name, count: 4}; });


Con .setIn() puedes hacer lo mismo:

let obj = fromJS({ elem: [ {id: 1, name: "first", count: 2}, {id: 2, name: "second", count: 1}, {id: 3, name: "third", count: 2}, {id: 4, name: "fourth", count: 1} ] }); obj = obj.setIn([''elem'', 3, ''count''], 4);

Si no conocemos el índice de la entrada que queremos actualizar. Es bastante fácil encontrarlo usando .findIndex() :

const indexOfListToUpdate = obj.get(''elem'').findIndex(listItem => { return listItem.get(''name'') === ''third''; }); obj = obj.setIn([''elem'', indexOfListingToUpdate, ''count''], 4);

¡Espero eso ayude!


El caso más apropiado es usar los métodos findIndex y de update .

list = list.update( list.findIndex(function(item) { return item.get("name") === "third"; }), function(item) { return item.set("count", 4); } );

PD: No siempre es posible usar Maps. Por ejemplo, si los nombres no son únicos y quiero actualizar todos los elementos con los mismos nombres.


Puedes usar el map :

list = list.map((item) => { return item.get("name") === "third" ? item.set("count", 4) : item; });

Pero esto se repetirá en toda la colección.


Realmente me gusta este enfoque del thomastuts web de thomastuts :

const book = fromJS({ title: ''Harry Potter & The Goblet of Fire'', isbn: ''0439139600'', series: ''Harry Potter'', author: { firstName: ''J.K.'', lastName: ''Rowling'' }, genres: [ ''Crime'', ''Fiction'', ''Adventure'', ], storeListings: [ {storeId: ''amazon'', price: 7.95}, {storeId: ''barnesnoble'', price: 7.95}, {storeId: ''biblio'', price: 4.99}, {storeId: ''bookdepository'', price: 11.88}, ] }); const indexOfListingToUpdate = book.get(''storeListings'').findIndex(listing => { return listing.get(''storeId'') === ''amazon''; }); const updatedBookState = book.setIn([''storeListings'', indexOfListingToUpdate, ''price''], 6.80); return state.set(''book'', updatedBookState);


Use .map()

list = list.map(item => item.get("name") === "third" ? item.set("count", 4) : item );

var arr = []; arr.push({id: 1, name: "first", count: 2}); arr.push({id: 2, name: "second", count: 1}); arr.push({id: 3, name: "third", count: 2}); arr.push({id: 4, name: "fourth", count: 1}); var list = Immutable.fromJS(arr); var newList = list.map(function(item) { if(item.get("name") === "third") { return item.set("count", 4); } else { return item; } }); console.log(''newList'', newList.toJS()); // More succinctly, using ES2015: var newList2 = list.map(item => item.get("name") === "third" ? item.set("count", 4) : item ); console.log(''newList2'', newList2.toJS());

<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>


var index = list.findIndex(item => item.name === "three") list = list.setIn([index, "count"], 4)

Explicación

La actualización de las colecciones de Immutable.js siempre devuelve nuevas versiones de esas colecciones dejando el original sin cambios. Por eso, no podemos usar la sintaxis de mutación list[2].count = 4 JavaScript. En su lugar, necesitamos llamar a métodos, como lo haríamos con las clases de colección de Java.

Comencemos con un ejemplo más simple: solo los recuentos en una lista.

var arr = []; arr.push(2); arr.push(1); arr.push(2); arr.push(1); var counts = Immutable.List.of(arr);

Ahora, si quisiéramos actualizar el tercer elemento, una matriz JS simple podría verse así: counts[2] = 4 . Como no podemos usar la mutación y necesitamos llamar a un método, en su lugar podemos usar: counts.set(2, 4) : eso significa establecer el valor 4 en el índice 2 .

Actualizaciones profundas

Sin embargo, el ejemplo que dio tiene datos anidados. No podemos usar set() en la colección inicial.

Las colecciones Immutable.js tienen una familia de métodos con nombres que terminan en "In" que le permiten realizar cambios más profundos en un conjunto anidado. Los métodos de actualización más comunes tienen un método "In" relacionado. Por ejemplo, para set hay setIn . En lugar de aceptar un índice o una clave como primer argumento, estos métodos "En" aceptan una "ruta de clave". La ruta de la clave es una matriz de índices o claves que ilustra cómo llegar al valor que desea actualizar.

En su ejemplo, deseaba actualizar el elemento en la lista en el índice 2, y luego el valor en la clave "contar" dentro de ese elemento. Entonces la ruta clave sería [2, "count"] . El segundo parámetro para el método setIn funciona igual que set , es el nuevo valor que queremos poner allí, así que:

list = list.setIn([2, "count"], 4)

Encontrar el camino clave correcto

Yendo un paso más allá, en realidad dijiste que querías actualizar el elemento donde el nombre es "tres", que es diferente al solo tercer elemento. Por ejemplo, ¿tal vez su lista no está ordenada, o tal vez allí el elemento llamado "dos" fue eliminado anteriormente? ¡Eso significa que primero debemos asegurarnos de que realmente conocemos la ruta de clave correcta! Para esto podemos usar el método findIndex() (que, por cierto, funciona casi exactamente como Array#findIndex ).

Una vez que hayamos encontrado el índice en la lista que tiene el elemento que queremos actualizar, podemos proporcionar la ruta clave al valor que deseamos actualizar:

var index = list.findIndex(item => item.name === "three") list = list.setIn([index, "count"], 4)

NB: Set vs Update

La pregunta original menciona los métodos de actualización en lugar de los métodos establecidos. Explicaré el segundo argumento en esa función (llamada updater ), ya que es diferente de set() . Mientras que el segundo argumento para set() es el nuevo valor que queremos, el segundo argumento para update() es una función que acepta el valor anterior y devuelve el nuevo valor que queremos. Entonces, updateIn() es la variación "In" de update() que acepta una ruta clave.

Digamos, por ejemplo, que queremos una variación de su ejemplo que no solo establezca el recuento en 4 , sino que incremente el recuento existente, podríamos proporcionar una función que agregue uno al valor existente:

var index = list.findIndex(item => item.name === "three") list = list.updateIn([index, "count"], value => value + 1)