Pasar de un código donde cada actualización de estado repite propiedad por propiedad el nuevo objeto, a funciones con nombres descriptivos que encapsulan esa lógica, es el primer paso real hacia un código más declarativo en React. Aquí se explica cómo abstraer esos set state dispersos en funciones reutilizables, por qué eso mejora la legibilidad y qué relación tiene con el camino hacia useReducer.
¿Por qué abstraer las actualizaciones del estado en funciones descriptivas?
Cuando se trabaja de forma imperativa con useState, cada lugar del código que necesita cambiar el estado repite el objeto completo con todas sus propiedades. Esto ocurre tanto con estados compuestos (un solo objeto con varias propiedades) como con estados independientes (varios useState separados) [00:47].
El problema crece con cada nuevo evento: onChange, onClick, validaciones dentro de useEffect… En cada sitio hay que escribir exactamente cuál es el nuevo estado. La solución es crear funciones actualizadoras del estado que tengan nombres que describan la acción, no la implementación. Así, en lugar de leer cinco líneas de propiedades, se lee una sola llamada: onConfirm(), onError(), onDelete() [01:30].
¿Cómo se crean las funciones actualizadoras paso a paso?
Se declaran antes del useEffect y cada una encapsula su correspondiente setState:
- onConfirm: se ejecuta cuando el código de seguridad es correcto. Limpia el value, pone error y loading en
false, y activa la pantalla de confirmación [02:15].
- onError: se dispara cuando el código escrito no coincide. Pone error en
true y loading en false [03:07].
- onWrite: reemplaza el evento onChange del input. Recibe como argumento
event.target.value y lo asigna internamente como newValue [04:30].
- onCheck: corresponde al botón de comprobar. Por dentro pone loading en
true, pero el nombre refleja la intención del usuario: verificar si el código es correcto [05:30].
- onDelete: pasa al estado de eliminación poniendo deleted en
true [06:40].
- onReset: regresa toda la aplicación al estado inicial, idéntico al valor que se pasa en el primer llamado a
React.useState [07:20].
¿Qué papel juegan los argumentos y el concepto de payload?
En el caso de onWrite, la función necesita recibir el valor que el usuario escribe. Se envía event.target.value como argumento y se recibe como parámetro newValue dentro de la función [04:55]. Este patrón de enviar datos junto con la acción tiene un nombre técnico: payload. Es exactamente el término que se utiliza cuando se trabaja con useReducer, la herramienta que lleva este enfoque declarativo al máximo [05:20].
¿Qué significa que el código sea "semideclarativo"?
La diferencia entre código imperativo y declarativo no es binaria. No existe una línea que separe ambos mundos; funciona más bien como un gradiente [09:25].
- En el extremo imperativo: cada actualización describe paso a paso qué propiedades cambian.
- En el extremo declarativo: solo se nombra la intención y la implementación queda oculta.
Con las funciones actualizadoras, el código queda a mitad de camino. El useEffect, por ejemplo, se vuelve mucho más limpio: solo contiene llamadas como onConfirm() y onError() en lugar de bloques con objetos detallados [04:05]. Sin embargo, internamente cada función sigue usando setState de forma directa, así que aún no se alcanza el máximo nivel declarativo.
¿Cómo se puede reutilizar una misma función para distintos eventos?
Un caso práctico es onReset. Tanto el botón de "no, me arrepentí" como el botón de "resetear" necesitan devolver la aplicación al estado inicial. Aunque uno de ellos no necesita poner deleted en false porque ya lo está, ambos pueden compartir la misma función sin problema [07:50].
javascript
const onReset = () => {
setState({
value: '',
error: false,
loading: false,
confirmed: false,
deleted: false,
});
};
Esta reutilización reduce duplicación y hace que los cambios futuros se apliquen en un solo lugar.
El siguiente paso natural para completar este camino declarativo es useReducer, que centraliza todas las transiciones de estado en un único reducer con acciones explícitas. Si ya entiendes las funciones actualizadoras y el concepto de payload, tienes la base para dar ese salto. ¿Ya pensaste en qué acciones de tu propia aplicación podrías abstraer de esta forma?