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
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.