Expo Router en React Native: Guia Completa de Navegacion Basada en Archivos
Guia completa de Expo Router para React Native en 2026. Navegacion basada en archivos, rutas dinamicas, tabs, modales, typed routes, middleware y proteccion de rutas con ejemplos de codigo.

Expo Router transforma la forma en que se estructura la navegacion en aplicaciones React Native al adoptar un sistema basado en archivos inspirado en frameworks web como Next.js. En lugar de declarar pilas de navegacion manualmente con React Navigation, cada archivo dentro del directorio app/ se convierte automaticamente en una ruta. Este enfoque reduce la configuracion repetitiva, centraliza la logica de navegacion y habilita funcionalidades avanzadas como deep linking universal, rutas tipadas y soporte nativo para web. Desde su version estable en 2024 hasta las mejoras introducidas en 2025 y 2026, Expo Router se ha consolidado como la solucion de navegacion preferida para proyectos Expo modernos.
Para crear un proyecto nuevo con Expo Router preconfigurado, basta con ejecutar npx create-expo-app@latest --template tabs. Este template incluye navegacion por pestanas, TypeScript y la estructura de archivos lista para produccion.
Como Funciona la Navegacion Basada en Archivos
El principio fundamental de Expo Router es sencillo: la estructura de archivos dentro del directorio app/ define las rutas de la aplicacion. Un archivo llamado index.tsx en la raiz se convierte en la pantalla principal, mientras que un archivo profile.tsx genera automaticamente la ruta /profile. No se necesita registrar rutas manualmente ni mantener un archivo centralizado de configuracion.
Cuando la aplicacion se inicia, Expo Router escanea el directorio app/, genera el mapa de rutas y configura el deep linking de forma automatica. Cada ruta funciona tanto en dispositivos moviles como en navegadores web sin configuracion adicional.
import { View, Text, StyleSheet } from 'react-native';
import { Link } from 'expo-router';
export default function HomeScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Welcome to My App</Text>
<Link href="/profile" style={styles.link}>
View Profile
</Link>
<Link href="/settings" style={styles.link}>
Settings
</Link>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 },
link: { fontSize: 16, color: '#2563eb', marginTop: 10 },
});El componente Link de Expo Router funciona de manera analoga a las etiquetas <a> en la web. Proporciona navegacion declarativa con soporte completo para deep linking, historial de navegacion y accesibilidad. A diferencia de navigation.navigate(), el componente Link mantiene la navegacion desacoplada de la logica de los componentes.
Estructura del Proyecto y Archivos de Layout
Expo Router utiliza archivos _layout.tsx para definir la estructura de navegacion que envuelve a las pantallas hijas. Los layouts permiten configurar headers, barras de pestanas, drawers y cualquier navegador compatible con React Navigation, todo desde la estructura del sistema de archivos.
Una estructura de proyecto tipica se organiza de la siguiente manera:
app/
├── _layout.tsx # Root layout (Stack navigator)
├── index.tsx # Home screen (/)
├── profile.tsx # Profile screen (/profile)
├── settings.tsx # Settings screen (/settings)
├── (tabs)/
│ ├── _layout.tsx # Tab navigator layout
│ ├── index.tsx # First tab (/)
│ ├── explore.tsx # Explore tab (/explore)
│ └── account.tsx # Account tab (/account)
├── (auth)/
│ ├── _layout.tsx # Auth group layout
│ ├── login.tsx # Login screen (/login)
│ └── register.tsx # Register screen (/register)
└── [id].tsx # Dynamic route (/:id)Los parentesis en los nombres de carpetas como (tabs) y (auth) crean grupos de rutas. Los grupos organizan archivos sin agregar segmentos a la URL: la ruta de (tabs)/explore.tsx es /explore, no /(tabs)/explore. Este mecanismo permite aplicar diferentes layouts a distintas secciones de la aplicacion sin afectar la estructura de URLs.
El archivo _layout.tsx raiz configura el navegador principal de la aplicacion:
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
export default function RootLayout() {
return (
<>
<StatusBar style="auto" />
<Stack
screenOptions={{
headerStyle: { backgroundColor: '#0f172a' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' },
contentStyle: { backgroundColor: '#020617' },
}}
>
<Stack.Screen name="index" options={{ title: 'Home' }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
</Stack>
</>
);
}Cada directorio puede contener su propio _layout.tsx, lo que permite componer layouts anidados. Una aplicacion puede tener un Stack en la raiz, un TabNavigator dentro de (tabs)/ y un Stack separado dentro de (auth)/, cada uno con su propia configuracion de encabezados y transiciones.
Construccion de Navegacion por Pestanas
La navegacion por pestanas es uno de los patrones mas comunes en aplicaciones moviles. Expo Router simplifica su implementacion mediante el componente Tabs, que se configura directamente en el archivo _layout.tsx del grupo correspondiente.
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#3b82f6',
tabBarInactiveTintColor: '#64748b',
tabBarStyle: {
backgroundColor: '#0f172a',
borderTopColor: '#1e293b',
},
headerStyle: { backgroundColor: '#0f172a' },
headerTintColor: '#fff',
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => (
<Ionicons name="home" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color, size }) => (
<Ionicons name="compass" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="account"
options={{
title: 'Account',
tabBarIcon: ({ color, size }) => (
<Ionicons name="person" size={size} color={color} />
),
}}
/>
</Tabs>
);
}Cada Tabs.Screen corresponde a un archivo dentro del directorio (tabs)/. El orden de declaracion en el layout determina el orden de las pestanas. Las opciones de personalizacion incluyen iconos, colores, badges y la posibilidad de ocultar pestanas especificas de forma condicional.
Rutas Dinamicas y Parametros de Ruta
Las rutas dinamicas permiten crear pantallas que responden a parametros variables. En Expo Router, un archivo cuyo nombre esta encerrado entre corchetes, como [id].tsx, captura el segmento correspondiente de la URL y lo expone como parametro.
import { View, Text, StyleSheet } from 'react-native';
import { useLocalSearchParams, Stack } from 'expo-router';
export default function ProductScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View style={styles.container}>
<Stack.Screen options={{ title: `Product ${id}` }} />
<Text style={styles.title}>Product Details</Text>
<Text style={styles.id}>Product ID: {id}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
title: { fontSize: 24, fontWeight: 'bold', marginBottom: 10 },
id: { fontSize: 16, color: '#94a3b8' },
});Para rutas que necesitan capturar multiples segmentos, Expo Router soporta rutas comodin con la sintaxis [...slug]. Este patron resulta especialmente util para sistemas de contenido donde las URLs tienen profundidad variable.
import { useLocalSearchParams } from 'expo-router';
import { View, Text } from 'react-native';
export default function DocsScreen() {
const { slug } = useLocalSearchParams<{ slug: string[] }>();
// /docs/getting-started/installation → slug = ['getting-started', 'installation']
return (
<View style={{ flex: 1, padding: 20 }}>
<Text>Documentation Path: {slug?.join('/')}</Text>
</View>
);
}Las rutas comodin capturan todos los segmentos restantes de la URL en un arreglo. La ruta /docs/getting-started/installation produce un arreglo ['getting-started', 'installation'] que el componente puede utilizar para renderizar el contenido correspondiente.
¿Listo para aprobar tus entrevistas de React Native?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Rutas Tipadas para Seguridad en Tiempo de Compilacion
Uno de los problemas recurrentes en la navegacion movil es pasar rutas como cadenas de texto sin ninguna verificacion en tiempo de compilacion. Expo Router resuelve este problema con typed routes, una funcionalidad que genera tipos de TypeScript automaticamente a partir de la estructura de archivos.
Para habilitar las rutas tipadas, se agrega la configuracion correspondiente en el archivo de configuracion del proyecto:
{
"expo": {
"experiments": {
"typedRoutes": true
}
}
}Con esta configuracion activa, el compilador de TypeScript detecta errores en las rutas antes de que la aplicacion se ejecute:
import { Link } from 'expo-router';
import { View, Text, Pressable } from 'react-native';
export default function CheckoutScreen() {
return (
<View style={{ flex: 1, padding: 20 }}>
<Text>Checkout</Text>
{/* Valid - TypeScript confirms route exists */}
<Link href="/product/123">View Product</Link>
{/* TypeScript Error: '/produc/123' is not assignable */}
{/* <Link href="/produc/123">View Product</Link> */}
{/* Valid - dynamic route with params */}
<Link
href={{
pathname: '/product/[id]',
params: { id: '456' }
}}
>
<Text>View Product 456</Text>
</Link>
</View>
);
}Las rutas tipadas eliminan una categoria completa de errores de navegacion. Si un archivo de ruta se renombra o se elimina, TypeScript reporta inmediatamente todas las referencias obsoletas en el codigo. Esta seguridad en tiempo de compilacion resulta particularmente valiosa en proyectos con decenas de pantallas donde los errores de tipeo en las rutas pueden pasar desapercibidos hasta la ejecucion.
Pantallas Modales y Opciones de Presentacion
Los modales son un patron de interfaz frecuente para formularios, confirmaciones y flujos secundarios. Expo Router permite definir pantallas modales directamente en el layout, controlando la animacion y la presentacion desde la estructura de archivos.
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen
name="modal"
options={{
presentation: 'modal',
headerTitle: 'Create Post',
animation: 'slide_from_bottom',
}}
/>
<Stack.Screen
name="create-post"
options={{
presentation: 'transparentModal',
animation: 'fade',
headerShown: false,
}}
/>
</Stack>
);
}La pantalla modal se implementa como cualquier otro componente, con acceso completo al router para cerrar el modal mediante navegacion:
import { View, Text, Pressable, StyleSheet } from 'react-native';
import { router } from 'expo-router';
export default function CreatePostModal() {
const handleSubmit = () => {
// Save post logic
router.back(); // Dismiss modal
};
return (
<View style={styles.overlay}>
<View style={styles.modal}>
<Text style={styles.title}>New Post</Text>
<Pressable onPress={handleSubmit} style={styles.button}>
<Text style={styles.buttonText}>Publish</Text>
</Pressable>
<Pressable onPress={() => router.back()} style={styles.cancel}>
<Text>Cancel</Text>
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
overlay: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.5)' },
modal: { backgroundColor: '#1e293b', padding: 24, borderRadius: 12, width: '90%' },
title: { fontSize: 20, fontWeight: 'bold', color: '#fff', marginBottom: 16 },
button: { backgroundColor: '#3b82f6', padding: 12, borderRadius: 8, alignItems: 'center' },
buttonText: { color: '#fff', fontWeight: '600' },
cancel: { marginTop: 12, alignItems: 'center' },
});Expo Router soporta las opciones de presentacion modal, transparentModal, fullScreenModal y containedModal. Cada opcion produce diferentes comportamientos de animacion y apariencia segun la plataforma, adaptandose automaticamente a las convenciones de iOS y Android.
Navegacion Programatica y la API del Router
Si bien el componente Link cubre la mayoria de los casos de navegacion declarativa, existen escenarios donde la navegacion debe ejecutarse en respuesta a eventos como el envio de formularios, la autenticacion exitosa o temporizadores. Expo Router expone el objeto router para estos casos.
import { router } from 'expo-router';
// Navigate forward (adds to history stack)
router.push('/product/123');
// Replace current screen (no back navigation)
router.replace('/dashboard');
// Go back to previous screen
router.back();
// Navigate with params
router.push({
pathname: '/product/[id]',
params: { id: '456', source: 'search' },
});
// Navigate to root and clear history
router.dismissAll();
router.replace('/');
// Check if we can go back
if (router.canGoBack()) {
router.back();
}Se recomienda utilizar router.push() cuando el usuario debe poder volver a la pantalla anterior, y router.replace() cuando la pantalla actual debe ser eliminada del historial, como despues de un inicio de sesion exitoso donde no tiene sentido volver a la pantalla de login.
La API del router incluye metodos para manipular el historial de navegacion, verificar si es posible retroceder, navegar con parametros tipados y descartar multiples pantallas de una sola vez. Todos los metodos respetan la configuracion de rutas tipadas cuando esta habilitada.
Middleware y Proteccion de Rutas
La proteccion de rutas es un requisito esencial en aplicaciones con autenticacion. Expo Router ofrece un sistema de middleware que permite interceptar las solicitudes de navegacion y redirigir a los usuarios segun su estado de autenticacion u otras condiciones.
import { createMiddleware } from 'expo-router/middleware';
export default createMiddleware({
redirect: {
'/dashboard': (req) => {
if (!req.auth?.isAuthenticated) {
return '/login';
}
},
'/admin/*': (req) => {
if (req.auth?.role !== 'admin') {
return '/unauthorized';
}
},
},
});Para una integracion mas profunda con la interfaz, la proteccion de rutas tambien puede implementarse directamente en los archivos de layout mediante redirecciones condicionales:
import { Redirect, Stack } from 'expo-router';
import { useAuth } from '@/hooks/useAuth';
import { ActivityIndicator, View } from 'react-native';
export default function DashboardLayout() {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#3b82f6" />
</View>
);
}
if (!isAuthenticated) {
return <Redirect href="/login" />;
}
return (
<Stack>
<Stack.Screen name="index" options={{ title: 'Dashboard' }} />
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
</Stack>
);
}Este patron de layout protegido garantiza que ninguna pantalla dentro del grupo (dashboard) se renderice sin autenticacion previa. El componente Redirect de Expo Router realiza la redireccion antes de que el contenido protegido se monte en el arbol de componentes.
Expo Router funciona de manera uniforme en iOS, Android y la web. Sin embargo, ciertos comportamientos de navegacion como gestos de retroceso, animaciones de transicion y la apariencia de los modales difieren entre plataformas. Es recomendable probar la navegacion en todas las plataformas de destino, especialmente cuando se utilizan opciones de presentacion modal o animaciones personalizadas.
Conclusion
Expo Router representa un avance significativo en la forma en que se aborda la navegacion en aplicaciones React Native. Al trasladar la configuracion de rutas al sistema de archivos, se eliminan capas de abstraccion que tradicionalmente agregaban complejidad a los proyectos moviles. Los aspectos fundamentales de Expo Router incluyen:
- Navegacion basada en archivos: cada archivo en el directorio
app/define una ruta automaticamente, eliminando la configuracion manual de navegadores - Layouts anidados: los archivos
_layout.tsxpermiten componer navegadores (Stack, Tabs, Drawer) de forma jerarquica sin codigo repetitivo - Rutas dinamicas: los segmentos
[id]y[...slug]capturan parametros de la URL con tipado completo de TypeScript - Rutas tipadas: la generacion automatica de tipos previene errores de navegacion en tiempo de compilacion
- Pantallas modales: las opciones de presentacion permiten definir modales directamente en la estructura del layout
- Navegacion programatica: la API del
routerofrece control completo sobre el historial y las transiciones de navegacion - Proteccion de rutas: el middleware y los layouts protegidos garantizan que las pantallas restringidas no se rendericen sin autorizacion
- Soporte multiplataforma: las rutas funcionan de forma identica en iOS, Android y la web con deep linking universal automatico
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

React Native: Desarrollo completo de una aplicación móvil en 2026
Guía completa para desarrollar aplicaciones móviles iOS y Android con React Native. Desde la configuración inicial hasta la publicación en tiendas, todos los fundamentos necesarios.

Componentes Standalone en Angular: Migracion desde NgModules y Buenas Practicas en 2026
Guia completa para migrar aplicaciones Angular de NgModules a componentes standalone. Incluye el proceso CLI en 3 pasos, lazy loading con loadComponent, manejo de SharedModules, pruebas unitarias, optimizacion de rendimiento y mejores practicas para desarrollo standalone-only en 2026.