Regístrate para acceder a más de 15 cursos gratuitos de programación con un simulador

Estado Complejo JS: Arquitectura Front-end

El concepto de estado incluye los datos de nuestra aplicación en cualquier momento dado, como por ejemplo las pestañas abiertas en un editor o navegador. Su cantidad y contenido cambian según las acciones que realicemos al presionar botones o intentar cargar información. En términos generales, cualquier cambio visual en la aplicación o página siempre implica un cambio en el estado y no hay otra forma de afectarlo. Es imposible que una parte de una página web cambie mientras el estado permanece igual. La modificación de la visualización solo es posible mediante cambios en el estado.

Se podría pensar que las animaciones hechas con CSS no alteran nada en nuestra aplicación. Es cierto que las animaciones en CSS no están relacionadas directamente con nuestra aplicación, pero dentro del navegador existe un estado que cambia.

Un excelente ejemplo de estado es el de un formulario. Imagina un campo para ingresar un número de teléfono que detecta errores al ingresarlos y los muestra de inmediato. Si no hay errores, permite enviar el formulario; de lo contrario, bloquea el botón. ¿Qué constituye el estado en este caso? Primero, todos los datos introducidos en el formulario. Segundo, el estado de validez de esos datos: "válido" o "inválido". Basándose en este estado, se decide si se debe resaltar el campo de entrada con un borde rojo o no. Además, los propios errores que se deben mostrar también forman parte del estado.

Como podemos ver en el ejemplo, el estado se describe con un objeto JS normal que se crea al iniciar la aplicación:

// Constante porque el objeto de estado siempre permanece igual
const state = {
  // El estado del formulario se destaca en una propiedad separada,
  // ya que puede haber varios formularios en la página
  registrationForm: {
    valid: true,
    errors: [],
  }
};

Y la lógica del controlador se divide en dos procesos independientes: el primero es cambiar el estado y el segundo es mostrar ese estado en la pantalla:

input.addEventListener('input', (e) => {
  const inputValue = e.target.value;
  // Guardamos los datos ingresados
  state.registrationForm.value = inputValue;
  // Según el valor ingresado, se determina el estado del formulario, su validez.
  // Si el valor es incorrecto, marcamos el formulario como no válido,
  // de lo contrario, lo marcamos como válido
  if (inputValue.match(/^\d+$/)) {
    state.registrationForm.valid = true;
    state.registrationForm.errors = [];
  } else {
    state.registrationForm.valid = false;
    state.registrationForm.errors.push('wrong format');
  }

  // La desactivación del botón se determina por el estado de validez
  submit.disabled = !state.registrationForm.valid;

  // La presencia de errores (borde rojo) depende del estado de validez del formulario
  if (state.registrationForm.valid) {
    input.style.border = null;
  } else {
    input.style.border = 'thick solid red';
  }
});

Así es como funcionan todos los frameworks frontend modernos. El concepto de separar los datos de la aplicación de la apariencia externa no es nuevo, de hecho, en el desarrollo backend no hay otras opciones (afortunadamente).

Recomendaciones para organizar el estado

Qué se almacena en el estado

En las aplicaciones, no todos los datos pueden cambiar con el tiempo. Estos datos pueden incluir configuraciones, como tiempos de espera, diferentes claves de acceso o configuraciones de bibliotecas. Estos datos (se podría decir que son estáticos) no se almacenan en el estado. Es suficiente tener constantes separadas creadas directamente en el lugar de uso o importadas de un módulo de configuración especial:

// No muy bueno
const state = {
  // cosas varias
  httpTimeout: 1000,
  apiKey: 'mi hash súper secreto',
};

// Muy bueno
const httpTimeout = 1000;
const apiKey = 'mi hash súper secreto';

Objeto de estado

El estado en sí se organiza mejor como una sola constante que contiene un objeto. Es mucho más fácil seguir este objeto que un conjunto de constantes o variables diferentes. Además, como veremos más adelante, esto permite un seguimiento conveniente de los cambios para implementar la arquitectura MVC (Model View Controller // Modelo Vista Controlador), a la que nos estamos acercando lentamente.

// No muy bueno
const state = {
  estadoFormulario: { /* ... */ },
};

const publicaciones = [];
let conectado = false;

// Muy bueno
const state = {
  estadoFormulario: { /* ... */ },
  publicaciones: [],
  conectado: false,
};

Nomenclatura

El estado en sí es excelente, pero no menos importante es la nomenclatura adecuada de los datos dentro del estado. Por ejemplo, ¿qué significan las propiedades valid o connected en el objeto de estado? Se puede adivinar, pero sin analizar el código, no se puede entender a qué se refieren. Estas palabras son demasiado generales, no proporcionan contexto. Siempre es mejor especificar a qué se refieren:

// no muy bueno
const state = {
  valido: false,
  conectado: true,
}

// muy bueno
const state = {
  formularioRegistroValido: false,
  chatConectado: true,
}

Agrupación

Otra forma de facilitar la comprensión del estado es agrupar las propiedades relacionadas con un proceso específico. Por ejemplo, un formulario puede operar con docenas de propiedades diferentes. Si hay varios formularios en la página, el objeto de estado se aumentará rápidamente y será difícil entender a qué se refiere cada cosa, incluso con una buena nomenclatura.

// no muy bueno
const state = {
  formularioRegistroValido: false,
  formularioRegistroErrores: [],
  formularioRegistroValorNombre: '',
}

// muy bueno
const state = {
  formularioRegistro: {
    valido: false,
    errores: [],
    campos: {
      nombre: '',
    },
  },
};

Estructura visual

Un error común al formar el estado es vincular la estructura del estado al diseño visual. El problema con esta estructura es que si el diseño cambia (incluso un pequeño cambio en la disposición de los elementos), el objeto de estado dejará de reflejar la realidad y será necesario modificarlo.

// No muy bueno
const state = {
  bloqueCentral: {
    valido: true,
  },
  barraLateral: {
    valorFormulario: 'valor'
  },
};

// Muy bueno
const state = {
  registrationForm: {
    valid: false,
  },
  searchForm: {
    value: 'valor'
  },
};

Almacenamiento de elementos del DOM

El estado de la aplicación son los datos, no su representación. Por lo tanto, guardar elementos del DOM en el estado se considera una mala práctica. De hecho, esto sería volver a la estructura previa a la introducción del estado, cuando los datos se almacenaban dentro de la vista.


Materiales adicionales

  1. Nomenclatura en programación

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.

Obtener acceso
130
cursos
1000
ejercicios
2000+
horas de teoría
3200
test

Obtén acceso

Cursos de programación para principiantes y desarrolladores experimentados. Comienza tu aprendizaje de forma gratuita

  • 130 cursos, 2000+ horas de teoría
  • 1000 ejercicios prácticos en el navegador
  • 360 000 estudiantes
Al enviar el formulario, aceptas el «Política de privacidad» y los términos de la «Oferta», y también aceptas los «Términos y condiciones de uso»

Nuestros graduados trabajan en empresas como:

Bookmate
Health Samurai
Dualboot
ABBYY