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>