005. Estado Inmutable

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>
Scroll al inicio