Link & href
Navegación declarativa y enlaces que favorecen la precarga. Link se asigna a navegación similar a anclas en la web y objetivos de presión accesibles en nativo - router maneja flujos imperativos después de efectos secundarios.
Busca en todas las páginas de la documentación
Navegación declarativa y enlaces que favorecen la precarga. Link se asigna a navegación similar a anclas en la web y objetivos de presión accesibles en nativo - router maneja flujos imperativos después de efectos secundarios.
Tarjeta de referencia rápida - lista para copiar y pegar.
import { Link, router, type Href } from "expo-router";
import { Pressable, Text, View } from "react-native";
// Href de string - solo rutas estáticas
<Link href="/settings">Settings</Link>
// Href de objeto - segmentos dinámicos (preferido)
<Link href={{ pathname: "/orders/[id]", params: { id: "42" } }}>
Order 42
</Link>
// Imperativo después de mutación
router.replace("/(tabs)");
// Precarga en hover/focus (web) o manualmente
<Link href="/orders" prefetch />// src/navigation/routes.ts
import type { Href } from "expo-router";
export const routes = {
home: "/" as Href,
settings: "/settings" as Href,
orderDetail: (id: string): Href => ({
pathname: "/orders/[id]",
params: { id },
}),
};Cuándo usarlo:
Link - filas de lista, enlaces de texto en línea, navegación adyacente a pestañas, anclas web amigables con SEOrouter.push - navega después de enviar formulario, escanear código QR o devolución de llamada de temporizadorrouter.replace - post-inicio de sesión, post-cierre de sesión, finalización de incorporaciónprefetch - pantallas con bundles pesados o cascadas de datos lentasPantalla de lista con Link, Pressable personalizado mediante asChild, navegación imperativa y constructores de href centralizados.
// src/navigation/routes.ts
import type { Href } from "expo-router";
export function orderDetailHref(id: string): Href {
return { pathname: "/orders/[id]", params: { id } };
}
export function settingsHref(): Href {
return "/settings";
}// features/orders/ui/OrdersListScreen.tsx
import { Link, router } from "expo-router";
import { Pressable, Text, View } from "react-native";
import { orderDetailHref } from "@/navigation/routes";
const ORDERS = [
{ id: "101", label: "Widget shipment" },
{ id: "102", label: "Replacement part" },
];
export function OrdersListScreen() {
return (
<View style={{ flex: 1, padding: 16, gap: 12 }}>
{ORDERS.map((order) => (
<Link key={order.id} href={orderDetailHref(order.id)} prefetch asChild>
<Pressable style={{ padding: 12, backgroundColor: "#f1f5f9", borderRadius: 8 }}>
<Text>{order.label}</Text>
</Pressable>
</Link>
))}
<Link href="/settings">Account settings</Link>
<Pressable
onPress={() => router.push(orderDetailHref("draft"))}
accessibilityRole="button"
>
<Text>Create draft (imperative)</Text>
</Pressable>
</View>
);
}// Después de enviar formulario exitoso - replace evita la pila de vuelta al formulario
import { router } from "expo-router";
async function onSubmit() {
await saveProfile();
router.replace("/(tabs)/profile");
}// Descartar flujo modal
import { router } from "expo-router";
function closeModal() {
if (router.canGoBack()) {
router.back();
} else {
router.replace("/");
}
}href| Forma | Ejemplo | Rutas tipificadas |
|---|---|---|
| Ruta de string | "/settings" | Rutas estáticas |
| Objeto | { pathname: "/orders/[id]", params: { id } } | Rutas dinámicas |
| Relativa | "./details" | Hermana dentro de carpeta |
| Externa | "https://expo.dev" | Abre navegador / aplicación externa |
// Navegación relativa dentro de app/orders/
<Link href="./[id]" params={{ id: "5" }}>Relative</Link>href="/search?q=shoes" o params: { q: "shoes" } dependiendo de la forma de rutapathname inválidos fallen en tiempo de compilación - ver Typed RoutesLink vs router| API | Estilo | Mejor para |
|---|---|---|
<Link href> | Declarativa | Listas, navegación en línea, precarga |
router.push | Imperativa | Post-async, redirecciones programáticas |
router.replace | Imperativa | Transiciones de autenticación, sin vuelta |
router.back | Imperativa | Cancelar, descartar modal |
router.navigate | Imperativa | Ir a ruta si existe, sino hacer push (como web) |
// Props de Link que importan en producción
<Link
href="/orders"
prefetch // precargar módulo de ruta
replace // reemplazar historial en lugar de hacer push
push // forzar push incluso cuando replace podría ser predeterminado
asChild // fusionar en Pressable hijo
disabled={!isReady}
/>prefetch en Link - Expo Router carga el bundle de JavaScript de la ruta de destino por adelantado antes de la navegaciónasChild<Link href="/settings" asChild>
<Pressable style={styles.row}>
<Text>Settings</Text>
</Pressable>
</Link>onPress, href en web) - usa Pressable o componentes personalizados que propagan propsLinkaccessibilityRole="link" en web; Pressable hereda comportamiento de link de Link// packages/navigation/src/hrefs.ts (monorepo)
export const orderDetailHref = (id: string) =>
({ pathname: "/orders/[id]", params: { id } }) as const;packages/navigation cuando las formas de ruta coincidenConcatenación de strings para rutas dinámicas - href={'/orders/' + id} elude rutas tipificadas y se rompe cuando los segmentos cambian. Solución: Forma de objeto o orderDetailHref(id).
router.push después de inicio de sesión - el gesto de vuelta regresa al inicio de sesión. Solución: router.replace.
Link envolviendo componentes sin envío de props - filas personalizadas ignoran presión. Solución: asChild + propagar props, o usar Pressable.
URLs externas en router.push - puede que no abra navegador. Solución: import { openURL } from "expo-linking" para enlaces https://.
Precargando rutas protegidas - parpadea contenido no autorizado. Solución: Gatea precarga detrás de verificación de sesión u omite en pantallas de autenticación.
Falta de accessibilityRole en Pressable imperativo - los lectores de pantalla anuncian "botón" para navegación. Solución: accessibilityRole="link" o prefiere Link.
Enormes cargas de parámetros en href - inflación de estado de navegación, registros filtran datos. Solución: Pasa solo IDs; carga cuerpos desde almacén o API.
| Alternativa | Úsalo cuando | No lo uses cuando |
|---|---|---|
<Link href> | Navegación predeterminada de lista/en línea | Después de mutación async antes de navegar |
router.push / replace | Control imperativo | Necesitas precarga y semántica de link |
useNavigation().navigate | Escape hatch de React Navigation | Existen rutas Expo Router estándar |
Componente Redirect | Puerta de autenticación declarativa en layout | Navegación activada por botón |
| Deep link URL manualmente | Carga útil de notificaciones push | Taps en la app - usa href tipificado |
href string | Prototipos rápidos | Rutas dinámicas de producción |
Link para UI que el usuario puede pulsar que navega a una ruta conocida.router.push después de que se complete el trabajo async (guardar, escanear, conceder permiso).router.replace cuando el botón de atrás no debe volver a la pantalla actual.router.push({ pathname: "/search", params: { q: "shoes", sort: "price" } });Lee con useLocalSearchParams(). Prefiere segmentos de ruta para IDs de entidad; consulta para filtros.
Sí - Link renderiza un ancla en la web con navegación del lado del cliente. Los valores href de string mejoran la capacidad de búsqueda para compilaciones web públicas.
<Link href="/checkout" disabled={!cartReady} asChild>
<Pressable disabled={!cartReady}>
<Text>Checkout</Text>
</Pressable>
</Link>Establece disabled tanto en Link como en el hijo cuando uses asChild.
Retorna si la pila tiene una pantalla anterior. Úsalo antes de router.back() en modales abiertos mediante deep link - vuelve a router.replace("/").
import * as Linking from "expo-linking";
await Linking.openURL("https://docs.expo.dev/router/introduction/");No pases URLs externas a router.push a menos que hayas configurado manejadores de enlaces externos.
Prefiere <Link prefetch />. Para casos avanzados, consulta los documentos de Expo Router SDK 57 para utilidades de prefetch en la instancia de router - la disponibilidad evoluciona por versión menor.
./[id] se resuelve relativo al directorio de la ruta actual - útil dentro de hermanas de app/orders/. Prefiere constructores absolutos en módulos compartidos para claridad.
navigate desduplica si la ruta ya está enfocada (como web). push siempre agrega una entrada de pila. Usa push para pilas de detalle duplicadas intencionales; navigate para comportamiento similar a pestañas.
Tipo de retorno Href desde expo-router. Con experiments.typedRoutes, pathnames inválidos generan un error en tiempo de compilación. Ver Typed Routes.
Href en tiempo de compilaciónRedirect vs router.replaceLink vs imperativaVersiones 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