La inmutabilidad del estado es uno de los temas clave en React. Es fácil de seguir cuando trabajamos con tipos de datos primitivos, pero puede resultar complicado para un usuario no preparado cuando se trata de tipos de datos compuestos como objetos y arrays. En esta lección vamos a explorar las formas básicas de actualizar parcialmente objetos y arrays.
Además de los ejemplos en JS puro, vamos a mostrar ejemplos utilizando la biblioteca immutability-helper, que se creó para facilitar este tipo de operaciones. Es especialmente útil cuando el código en JS se vuelve demasiado complejo.
Arrays
Array: agregar
Lo más sencillo es agregar elementos a un array:
const items = ['uno', 'dos', 'tres'];
const item = 'cuatro';
const newItems = [...items, item];
// ['uno', 'dos', 'tres', 'cuatro'];
Si deseas agregar un elemento al principio, solo necesitas intercambiar los elementos del array:
const newItems = [item, ...items];
// ['cuatro', 'uno', 'dos', 'tres'];
Uso de immutability-helper
import update from 'immutability-helper';
const state1 = ['x'];
const state2 = update(state1, { $push: ['y'] }); // ['x', 'y']
Array: eliminar
Un ejemplo más interesante. Para eliminar con éxito, necesitamos saber qué queremos eliminar. Esto significa que cada elemento en la lista debe tener un identificador. Para eliminar, utilizamos el buen y viejo filtrado.
const newItems = items.filter((item) => item.id !== id);
Puede surgir la pregunta: ¿de dónde viene el identificador dentro del controlador? Aquí es donde entran en juego los cierres.
Ver el Pen js_react_immutability_array_remove_element de Códica (@hexlet) en CodePen.
Observa la forma en que se define el controlador: removeItem = (id) => (e) => { y cómo se utiliza onClick={this.removeItem(id)}.
Uso de immutability-helper
const index = 5;
const newItems = update(items, {$splice: [[index, 1]]});
Eliminar mediante filtrado en JS puro es la forma más óptima. Con immutability-helper, se vuelve más complicado.
Array: modificar
Desafortunadamente, sin herramientas adicionales, el código de la solución se vuelve demasiado engorroso. Se proporciona como referencia, pero no recomendamos utilizarlo en código real.
const index = items.findIndex((item) => item.id === id);
const newItem = { ...items[index], value: 'otro valor' };
const newItems = [...items.slice(0, index), newItem, ...items.slice(index + 1)];
Uso de immutability-helper
const collection = { children: ['cero', 'uno', 'dos'] };
const index = 1;
const newCollection = update(collection, { children: { [index]: { $set: 1 } } });
// { children: ['cero', 1, 'dos'] }
Como puedes ver, este método es mucho más sencillo y limpio, así que recomendamos su uso.
Objetos
Objeto: agregar
Tan sencillo como con un array.
const items = { a: 1, b: 2 };
const newItems = { ...items, c: 3 };
// { a: 1, b: 2, c: 3 }
O, si la clave se calcula dinámicamente, debes hacer lo siguiente:
const items = { a: 1, b: 2 };
const key = 'c';
const newItems = { ...items, [key]: 3 };
// { a: 1, b: 2, c: 3 }
Objeto: eliminar
La desestructuración es útil en este caso:
const { deletedKey, ...newState } = state;
Uso de immutability-helper
import update from 'immutability-helper';
const state = { a: 1, c: 3 };
const updatedState = update(state, {
$unset: ['c'],
});
// { a: 1 }
Objeto: modificar
Es exactamente igual que agregar.
const items = { a: 1, b: 2 };
const newItems = { ...items, a: 3 };
// { a: 3, b: 2 }
Uso de immutability-helper
const data = { a: 1, b: 2 };
const key = 'a';
const newData = update(data, { [key]: { $set: 3 } });
// { a: 3, b: 2 }
Anidamiento profundo
En los ejemplos anteriores, en su mayoría se pueden utilizar las funciones estándar de JS, y solo en algunas situaciones es más conveniente utilizar soluciones de terceros. En el código real, esto será igual, especialmente si se tiene en cuenta la recomendación de React de mantener el estado lo más plano posible. Sin embargo, en algunas situaciones, los datos que queremos modificar no están en la superficie, sino en lo profundo de las estructuras. Desafortunadamente, en estas situaciones, el código JS normal se vuelve engorroso. Y aquí es cuando definitivamente necesitamos una biblioteca adicional.
import update from 'immutability-helper';
const myData = {
x: { y: { z: 5 } },
a: { b: [1, 2] },
};
const newData = update(myData, {
x: { y: { z: { $set: 7 } } },
a: { b: { $push: [9] } }
});
console.log(newData)
// => { x: { y: { z: 7 } }, a: { b: [ 1, 2, 9 ] } }
Alternativas
immutability-helper no es la única biblioteca para este tipo de tareas. Aquí hay algunas otras populares:
- immutable-js es una biblioteca basada en datos persistentes.
- updeep es una biblioteca que utiliza ampliamente el currying.
- immerjs es probablemente la biblioteca más popular en JS para trabajar con datos inmutables.
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.