En el capítulo anterior logramos que nuestro estado reaccionara de manera reactiva y renderizara la UI, sin embargo todavía es un estado mutable, es decir, podemos acceder directamente al state y modificarlo, y el objetivo de un estado es su inmutabilidad.
Para poder hacer un estado inmutable, lo que vamos a hacer en este capítulo es, antes de actualizar el estado, obtener una copia de ese estado. Crearemos una nueva función que nos va a permitir obtener una copia inmutable del estado, la función es getState().
Vamos a crear un archivo que se llame 03_estado-inmutable.js.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Estado inmutable</title>
</head>
<body>
<h1>Estado inmutable</h1>
<form id="todo-form">
<input type="text" id="todo-item" placeholder="Tarea por hacer" />
<input type="submit" value="Agregar" />
</form>
<h2>Lista de tareas</h2>
<ul id="todo-list"></ul>
<script>
const d = document;
// El State
const state = {
todoList: [],
nombre: "",
};
// Template
const template = () => {
if (state.todoList.length < 1) {
return `<p><em>Lista sin tareas por hacer</em></p>`;
}
let todos = state.todoList.map((item) => `<li>${item}</li>`).join("");
return todos;
};
// Render UI
const render = () => {
console.log(state);
const $list = d.getElementById("todo-list");
if (!$list) return;
$list.innerHTML = template();
};
// Actualizar el State de manera reactiva
const setState = (obj) => {
for (let key in obj) {
if (state.hasOwnProperty(key)) {
state[key] = obj[key];
}
}
render();
};
// Obteniendo una copia inmutable del State
const getState = () => JSON.parse(JSON.stringify(state));
d.addEventListener("DOMContentLoaded", render);
// Estableciendo valores por defecto al state
setState({
todoList: ["Tarea 1", "Tarea 2", "Tarea 3"],
nombre: "Francisco",
});
// Estado mutable, ya que permite modificar el estado directamente creando una copia del objeto y agregando otro elemento
const items = getState();
// items.push("Tarea 10");
items.todoList.push("Tarea 100");
d.addEventListener("submit", (e) => {
if (!e.target.matches("#todo-form")) return false;
e.preventDefault();
const $item = d.getElementById("todo-item");
if (!$item) return;
// Actualizar el State de forma reactiva
const lastState = getState();
lastState.todoList.push($item.value);
setState({
todoList: lastState.todoList,
});
// Limpiar el input
$item.value = "";
$item.focus();
});
</script>
</body>
</html>
