Prácticas recomendadas avanzadas de Expo Router
Un resumen condensado de las 25 prácticas recomendadas más importantes extraídas de todas las páginas de esta sección.
Busca en todas las páginas de la documentación
Un resumen condensado de las 25 prácticas recomendadas más importantes extraídas de todas las páginas de esta sección.
Anida un navegador por _layout.tsx: Cada layout de carpeta exporta exactamente uno Stack, Tabs, NativeTabs, SplitView, o Slot/Navigator headless - mezclar dos navegadores en un archivo de layout crea un historial ambiguo.
Dale a cada pestaña su propio stack cuando hagas push de detalles: Pon home/_layout.tsx → <Stack /> bajo cada pestaña que necesite lista - detalles; las carpetas de pestaña planas pierden stacks de retroceso independientes.
Navega con hrefs absolutos a través de límites de pestañas: Prefiere router.push('/inbox/t2') sobre rutas relativas ../ cuando cruces pestañas - los segmentos relativos se resuelven contra el contexto del navegador actual.
Ancla rutas modales para deep links: Exporta unstable_settings = { anchor: '(tabs)' } en el stack que posee modales para que el inicio en frío de /compose no limpie el shell de pestaña.
Usa router.replace después de transiciones de autenticación: Login, logout y cambios de rol deben reemplazar el historial - push permite a los usuarios deslizarse de vuelta a pantallas de credenciales o rol obsoleto.
Hidrata la sesión antes de renderizar Stack.Protected: Mantén visible el splash hasta que se complete la lectura de SecureStore/token - renderizar guardias mientras isLoading causa parpadeo de redirección y bucles.
Autoridad única para puertas de autenticación: Los grupos Stack.Protected en root vencen al dispersar <Redirect /> en cada layout anidado - los redirects en competencia causan rebotes infinitos entre / y /sign-in.
Nunca duplices pantallas entre grupos Protected: Un archivo de ruta puede aparecer en solo una declaración Stack.Protected - anida guardias para roles en lugar de copiar profile en dos grupos.
Trata Protected como UX, no como seguridad: Las guardias del cliente no eliminan rutas del bundle - valida cada llamada de API del lado del servidor; consulta ../auth-session/.
Elige modales de Expo Router sobre RN <Modal> para flujos enlazables: Las rutas presentation: 'modal' participan en deep links y Android back - reserva RN Modal para alertas efímeras sin URL.
Renderiza el chrome de hoja de formulario en el contenido en Android: Los headers de pila nativa y las pilas anidadas dentro de formSheet no se renderizan en Android - el título y las acciones pertenecen al cuerpo de la hoja.
Limita los detents de hoja de formulario a tres en Android: sheetAllowedDetents con más de tres valores se trunca - diseña hojas multiplataforma con ≤3 puntos de ajuste.
Declara cada pestaña nativa con NativeTabs.Trigger: A diferencia de Tabs de JavaScript, los archivos no se añaden automáticamente a la barra - los disparadores faltantes significan que las rutas existen pero son inalcanzables desde la UI de la barra de pestañas.
No uses disabled en pestañas nativas para autorización: disabled solo bloquea los taps de la barra de pestañas - router.push aún navega; usa Stack.Protected u hidden para la verdadera eliminación.
Resuelve la visibilidad de pestañas con feature-flag antes del primer montaje: Cambiar hidden en NativeTabs.Trigger en tiempo de ejecución remonta el navegador y limpia stacks - decide conjuntos de pestañas en el arranque.
Impulsa master-detail de tablet desde segmentos de URL: El estado de selección pertenece a rutas [id].tsx, no a useState(selectedId) - los deep links y la rotación se restauran correctamente.
Envía respaldo responsive split para tabletas Android: SplitView es alpha nativa de iOS - usa useWindowDimensions + diseño de fila y Stack por sección en Android y anchos estrechos.
Muestra un marcador de posición de detalle vacío en tablet: /orders sin un id debe renderizar "Selecciona un pedido" en el panel secundario - la paridad del cliente de correo previene columnas confusas en blanco.
Limítate a un SplitView por aplicación: Anidar vistas divididas o colocarlas dentro de pestañas lanza excepciones - split pertenece a root con secciones de barra lateral reemplazando pestañas inferiores en iPad.
Comienza RSC solo con Server Functions en SDK 57: Habilita reactServerFunctions dentro de rutas cliente normales - evita reactServerComponentRoutes en producción hasta que soporte de Stack/Tabs regrese.
Envuelve la UI de Server Function transmitida en Suspense: Cada llamada renderX() desde "use server" necesita <React.Suspense fallback={…}> - de lo contrario, los estados de carga bloquean toda la pantalla.
Alcanza <Slot /> antes del Navigator personalizado: El chrome headless (headers, progreso de onboarding) rara vez necesita useNavigationBuilder - los navegadores personalizados aumentan el mantenimiento e importar superficie de SDK.
Importa primitivas de navegación desde rutas expo-router: Las rutas SDK 56+ @react-navigation/* a través de expo-router y expo-router/react-navigation - las importaciones de paquete directo se rompen en la actualización.
Pasa el parámetro de consulta redirect a través del inicio de sesión: Los deep links al contenido protegido deben reanudar post-login mediante router.replace(redirect ?? '/(tabs)') - no descartes el destino previsto.
Prueba deep links de inicio en frío en matrices de CI: Verifica myapp://inbox/t2, anclajes modales, redirects cerrados y Android hardware back en cada lanzamiento - los retrocesos de navegación son incidentes de producción.
useSegments()).Stack.Protected / Tabs.Protected en root.app/index.tsx solo para ruta de destino predeterminada.Tabs cuando necesites Tabs.Protected dentro del layout de pestaña o JSX de barra de pestañas completamente personalizado.isLoading antes de cualquier navegador.Stack.Protected en root.router.replace después del login.index.tsx duplicado en grupos en competencia.renderRouter para navegación href y redirects Protected.Versiones de Stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0, y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 19 jul 2026