La Arquitectura Limpia separa lo que hace la app (entidades, casos de uso) de cómo habla con el mundo (adaptadores). En React Native, eso significa casos de uso comprobables en TypeScript - no fábricas abstractas para cada pulsación de botón.
Caso de uso por clic de botón - Cientos de casos de uso "de una línea" añaden ruido. Solución: Casos de uso para intenciones de varios pasos; mantén toggles triviales en hooks.
Puertos para todo incluyendo Date.now() - Abstrae el tiempo solo cuando las pruebas demuestran inestabilidad. Solución: Inyecta relojes solo en flujos de pago/expiración.
Lanzar errores entre capas - Los llamadores no pueden distinguir fallos de red vs validación. Solución: Retorna uniones discriminadas ({ ok: false, error: "network" }).
Hooks que llaman fetch directamente - Evita casos de uso; las pruebas necesitan MSW para cada pantalla. Solución: Mueve IO a adaptadores; los hooks llaman casos de uso.
Las entidades importan adaptadores - Invierte la regla de dependencia. Solución: Los adaptadores importan tipos de entidad; los casos de uso dependen de interfaces de puerto.
Dios domain/ compartido entre todas las características - Se convierte en un monolito. Solución: Por-característica domain/ a menos que la entidad sea verdaderamente global (User - entities/user).
TanStack Query dentro de casos de uso - Query es una preocupación de caché de presentación. Solución: El caso de uso retorna datos; el hook o adaptador de repositorio alimenta el cliente de query.
¿Es Arquitectura Limpia excesiva para React Native?
La ceremonia completa es excesiva para apps pequeñas. Adopta entidades + casos de uso + adaptadores para características con reglas de negocio reales (auth, pagos, sincronización offline). Las listas CRUD pueden permanecer hook + módulo de API.
¿Dónde viven los casos de uso?
Dentro de la característica: src/features/auth/domain/use-cases/. Las reglas entre características pertenecen a src/entities/<name>/ o un paquete de dominio compartido.
¿Necesito interfaces para cada adaptador?
Añade una interfaz de puerto cuando tienes dos implementaciones (API en vivo + mock, o REST + GraphQL). Un adaptador único puede usar un tipo concreto hasta que exista la segunda implementación.
¿Cómo funciona esto con Expo Router?
Las rutas permanecen delgadas. SignInScreen recibe onSignedIn de la ruta; la navegación es una preocupación de capa externa - no dentro del caso de uso.
¿Deben los casos de uso retornar entidades o DTOs?
Retorna entidades o tipos de resultado específicos de característica. Mapea DTOs de API a entidades dentro de adaptadores - las formas de DTO nunca se filtran a la UI.
¿Pueden los casos de uso llamar otros casos de uso?
Sí, combínalos - checkout puede llamar validateCoupon e reserveInventory. Mantén la composición en un caso de uso padre, no en la UI.
¿Dónde encaja Zustand?
Zustand sostiene estado de UI de cliente o un caché de sesión actualizado por resultados de caso de uso. No pongas lógica fetch dentro de acciones de store - llama casos de uso desde acciones en su lugar.
¿Cómo pruebo signIn sin un dispositivo?
Pasa objetos AuthGateway y TokenStorage falsos a signIn(). Afirma sobre la unión discriminada - no se requiere renderizador.
¿Qué pasa con la sincronización offline-first?
Modela SyncQueue como un puerto. El caso de uso enqueueMutation escribe a adaptador de cola; el adaptador worker en background drena la cola - la UI llama casos de uso, no SQLite directamente.
¿Es Redux una capa de arquitectura limpia?
Redux es estado de infraestructura/presentación. Los casos de uso no deben despachar acciones de Redux - los hooks despachan después de que los casos de uso tengan éxito.
¿Cómo es esto diferente de FSD?
FSD es taxonomía de carpetas. Clean Architecture es dirección de dependencia dentro de esas carpetas. Usa segmentos de FSD (domain/, adapters/) para albergar anillos limpios.
¿Cuándo debo extraer entidades a src/entities/?
Cuando dos o más características importan el mismo sustantivo (User, Order). Las entidades locales de característica permanecen en features/<name>/domain/ hasta compartirse.
¿Necesito DI de estilo Dagger/Hilt?
No. Funciones factory simples y contexto de React son suficientes - véase Inyección de Dependencia en RN.
¿Cuántas líneas antes de que un hook se convierta en un caso de uso?
El conteo de líneas es una señal débil. Extrae cuando el hook mezcla IO + reglas de negocio ramificadas + estado de UI y las pruebas requieren montar React - típicamente 40+ líneas de orquestación.