Escalar con tecnología:

Arquitectura Frontend: RTK Query, Zustand, Hooks

En el ciclo de vida del desarrollo de software, escribir el código es solo el comienzo. El verdadero desafío, especialmente en sistemas empresariales complejos, reside en el mantenimiento y la evolución constante. Cuando una aplicación crece, lo que funcionaba para un MVP (Producto Mínimo Viable) deja de ser sostenible: los componentes se vuelven gigantescos, la gestión del estado se enreda y cada nueva funcionalidad introduce el riesgo de romper algo existente.

Desde nuestra área de I+D, hemos analizado este escenario para redefinir nuestra arquitectura frontend. No buscamos simplemente adoptar nuevas tendencias, sino resolver un problema estructural:

¿Cómo construimos sistemas que puedan escalar indefinidamente sin volverse inmanejables?

La respuesta no está en una sola librería, sino en la aplicación rigurosa de principios de diseño como SOLID, específicamente el Principio de Responsabilidad Única (SRP), y una clara separación entre los diferentes tipos de estado que maneja una aplicación.

El problema de la arquitectura monolítica en el frontend

Tradicionalmente, muchas aplicaciones React han adoptado un enfoque monolítico implícito. Vemos componentes que acumulan responsabilidades: renderizan la UI, llaman a la API, transforman datos y gestionan el estado de los formularios, todo en el mismo archivo.

A esto se suma el uso de herramientas como Redux para absolutamente todo. Si bien Redux es extremadamente robusto, usarlo para estados triviales de UI (como abrir un modal) o para cachear respuestas de API genera una cantidad innecesaria de boilerplate y complejidad.

Las consecuencias de este enfoque en sistemas vivos son claras:

  • Violación del SRP: La mezcla de lógica y presentación convierte cualquier modificación menor en un riesgo de regresión.
  • Dificultad de mantenimiento: La carga cognitiva para entender componentes sobrecargados ralentiza a los desarrolladores.
  • Baja reutilización: La lógica acoplada a la vista impide su reutilización en otros módulos, obligando a reescribir soluciones.

Un nuevo paradigma: modularidad y especialización

Para superar estas barreras, nuestra propuesta arquitectónica desacopla estrictamente las capas de la aplicación. Entendemos que la Interfaz de Usuario (UI) debe ser un mero reflejo de los datos, sin responsabilidad sobre cómo se obtienen o procesan esos datos.

Especialización del estado: Server State vs. Client State

Un pilar fundamental de esta arquitectura es distinguir entre los tipos de datos que operan en la aplicación:

  • Server State (datos del servidor): Son datos persistentes y remotos. Para su gestión, implementamos RTK Query. Esta herramienta automatiza la gestión de caché, reintentos y sincronización, eliminando el código manual y propenso a errores asociado a las peticiones asíncronas.
  • Client State (estado de UI): Son estados volátiles, propios de la sesión del usuario (filtros, menús, formularios). Para esto, adoptamos Zustand. Su API minimalista permite gestionar estos cambios de forma rápida y ligera, sin el «boilerplate» excesivo de soluciones anteriores.

El patrón de ingeniería: Custom Hooks y Contextos

A nivel de código, aplicamos el SRP extrayendo sistemáticamente la lógica de negocio hacia Custom Hooks.

¿Cómo se estructura esto en un módulo complejo? Tomemos como ejemplo un gestor de operaciones críticas:

  • La Lógica (useModuleList): Un custom hook actúa como el controlador. Encapsula las llamadas a la API, la gestión de errores, la paginación y las reglas de negocio. Retorna datos puros y funciones de acción.
  • La Presentación (Componente UI): Recibe los datos procesados y se limita a renderizarlos. Es un componente funcional puro que ignora la complejidad subyacente.

La Distribución (Context API): Para evitar la complejidad de pasar datos manualmente por múltiples niveles (prop drilling), utilizamos contextos que inyectan la lógica del hook y la disponibilizan en todo el árbol de componentes del módulo.

Otros temas

Caso de estudio real:
aplicación “Atención al Socio”

El desafío: Esta aplicación cuenta con una pantalla de operaciones crítica dividida en dos paneles interdependientes:

Permite seleccionar deportes (Fútbol, Basket, Vóley) y filtrar eventos específicos.
Su funcionalidad y disponibilidad dependen enteramente de la selección realizada en el panel superior.

Bajo un enfoque tradicional, el componente padre tendría que controlar el estado de ambos paneles, pasando múltiples props hacia abajo y acoplando la lógica de ambos sectores.

La solución modular:

Implementamos un Custom Hook (useEventsPanel) que encapsula exclusivamente la lógica de negocio del panel superior:

  • Gestiona el estado del deporte seleccionado y la apertura de eventos.
  • Calcula los parámetros de búsqueda (eventSearchParams).
  • Maneja la llamada a la API (useGetEventosQuery) y la selección automática del primer evento disponible.

Luego, utilizamos un Contexto (EventsPanelContext) que actúa como intermediario para distribuir esta lógica a los componentes visuales.

Finalmente, el subcomponente visual EventAutocomplete se mantiene fiel al SRP. No contiene lógica de negocio ni sabe cómo buscar los eventos; simplemente se conecta al contexto para obtener la lista eventos y la función setSelectedEvent, limitándose a renderizar el campo de texto.

Resultado: Logramos componentes visuales “puros” y una lógica de negocio aislada, testeable y reutilizable, eliminando la complejidad del componente contenedor.

Estructura de directorios escalable

En plataformas de gran envergadura, el orden es sinónimo de eficiencia. Hemos estandarizado una estructura modular donde cada funcionalidad de negocio (feature) opera como una unidad independiente dentro del directorio src/modules.

Esta jerarquía (Módulo > Submódulo > Componente) asegura que, sin importar el tamaño del equipo o la antigüedad del proyecto, cualquier desarrollador pueda localizar, entender y modificar una funcionalidad sin afectar el resto del sistema.

El valor estratégico de esta arquitectura

Implementar esta ingeniería de software no es solo una mejora técnica, es una decisión de negocio que impacta en la viabilidad del proyecto a largo plazo:

  1. Estabilidad en el cambio: Al aislar la lógica en hooks, podemos modificar reglas de negocio complejas sin riesgo de romper la interfaz visual.
  2. Calidad asegurada (testing): Es mucho más efectivo probar hooks de lógica aislada que intentar validar flujos complejos a través de la interfaz gráfica.
  3. Eficiencia del equipo: Permite que distintos perfiles trabajen en paralelo (lógica vs. UI) sin bloquearse, acelerando los tiempos de entrega.
  4. Preparados para escalar: La estructura modular permite agregar nuevas funcionalidades indefinidamente manteniendo la base de código limpia y ordenada.

Conclusión

La arquitectura de software debe responder a la realidad del negocio. Para sistemas que requieren alta disponibilidad, mantenimiento constante y evolución continua, el enfoque monolítico es un riesgo técnico. Adoptar una arquitectura modular, potenciada por herramientas modernas como React Query y Zustand, es la inversión necesaria para construir activos digitales sólidos que acompañen el crecimiento de la empresa.

¿Querés llevar la gestión de tu organización al siguiente nivel?

Contactanos hoy mismo y descubrí cómo el software a medida de Meta puede transformar tu operación.

También te puede interesar