006. Componentes con Estado

En esta filosofía de programación reactiva y orientada a componentes, cada pedacito de la UI puede ser un componente y a su vez ese componente tener una UI propiab. En este capítulo haremos que nuestros componentes tengan un estado o componente local.

Vamos a crear un archivo denominado 04_componentes-con-estado.html, que tiene la siguiente sintaxis.

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Componentes con Estado</title>
  </head>

  <body>
    <h1>Componentes con Estado</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 Global
      const state = {
        todoList: [],
        nombre: "",
      };

      // Template UI
      const template = () => {
        if (template.data.todoList.length < 1) {
          return `<p><em>Lista sin tareas por hacer</em></p>`;
        }

        let todos = template.data.todoList
          .map((item) => `<li>${item}</li>`)
          .join("");
        return todos;
      };

      // Agregar State al Template que genera el componente de UI (State Local)
      template.data = {
        todoList: [],
      };

      // Render UI
      const render = () => {
        console.log("Estado global", state);
        console.log("Estado local", template.data);
        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 (template.data.hasOwnProperty(key)) {
            template.data[key] = obj[key];
          }
        }
        render();
      };

      // Obteniendo una copia inmutable del State
      const getState = () => JSON.parse(JSON.stringify(template.data));
      d.addEventListener("DOMContentLoaded", render);

      // Estableciendo valores por defecto al state
      setState({
        todoList: ["Tarea 1", "Tarea 2", "Tarea 3"],
      });

      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