Rutas paralelas
El enrutamiento paralelo (Parallel Routing) le permite renderizar simultáneamente o condicionalmente una o más páginas en el mismo diseño. Para secciones altamente dinámicas de una aplicación, como paneles de control y feeds en sitios sociales, el enrutamiento paralelo puede usarse para implementar patrones de enrutamiento complejos.
Por ejemplo, puede renderizar simultáneamente las páginas de equipo y análisis.

El enrutamiento paralelo permite definir estados de error y carga independientes para cada ruta a medida que se transmiten por separado.

El enrutamiento paralelo también le permite renderizar condicionalmente un espacio (slot) basado en ciertas condiciones, como el estado de autenticación. Esto permite código completamente separado en la misma URL.

Convención
Las rutas paralelas se crean usando espacios (slots) con nombre. Los espacios se definen con la convención @folder
y se pasan al diseño del mismo nivel como props.
Los espacios no son segmentos de ruta y no afectan la estructura de la URL. La ruta de archivo
/@team/members
sería accesible en/members
.
Por ejemplo, la siguiente estructura de archivos define dos espacios explícitos: @analytics
y @team
.

La estructura de carpetas anterior significa que el componente en app/layout.js
ahora acepta las props de espacios @analytics
y @team
, y puede renderizarlos en paralelo junto con la prop children
:
export default function Layout(props: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{props.children}
{props.team}
{props.analytics}
</>
)
}
export default function Layout(props) {
return (
<>
{props.children}
{props.team}
{props.analytics}
</>
)
}
Nota importante: La prop
children
es un espacio implícito que no necesita mapearse a una carpeta. Esto significa queapp/page.js
es equivalente aapp/@children/page.js
.
Rutas no coincidentes
Por defecto, el contenido renderizado dentro de un espacio coincidirá con la URL actual.
En el caso de un espacio no coincidente, el contenido que Next.js renderiza difiere según la técnica de enrutamiento y la estructura de carpetas.
default.js
Puede definir un archivo default.js
para renderizar como respaldo cuando Next.js no pueda recuperar el estado activo de un espacio basado en la URL actual.
Considere la siguiente estructura de carpetas. El espacio @team
tiene un directorio settings
, pero @analytics
no.

Navegación
Durante la navegación, Next.js renderizará el estado activo previo del espacio, incluso si no coincide con la URL actual.
Recarga
Al recargar, Next.js primero intentará renderizar el archivo default.js
del espacio no coincidente. Si no está disponible, se renderizará un 404.
El 404 para rutas no coincidentes ayuda a asegurar que no renderice accidentalmente una ruta que no debería renderizarse en paralelo.
useSelectedLayoutSegment(s)
Tanto useSelectedLayoutSegment
como useSelectedLayoutSegments
aceptan un parallelRoutesKey
, que le permite leer el segmento de ruta activo dentro de ese espacio.
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default async function Layout(props: {
//...
auth: React.ReactNode
}) {
const loginSegments = useSelectedLayoutSegment('auth')
// ...
}
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default async function Layout(props) {
const loginSegments = useSelectedLayoutSegment('auth')
// ...
}
Cuando un usuario navega a @auth/login
, o /login
en la barra de URL, loginSegments
será igual a la cadena "login"
.
Ejemplos
Modales
El enrutamiento paralelo puede usarse para renderizar modales.

El espacio @auth
renderiza un componente <Modal>
que puede mostrarse navegando a una ruta coincidente, por ejemplo /login
.
export default async function Layout(props: {
// ...
auth: React.ReactNode
}) {
return (
<>
{/* ... */}
{props.auth}
</>
)
}
export default async function Layout(props) {
return (
<>
{/* ... */}
{props.auth}
</>
)
}
import { Modal } from 'components/modal'
export default function Login() {
return (
<Modal>
<h1>Iniciar sesión</h1>
{/* ... */}
</Modal>
)
}
import { Modal } from 'components/modal'
export default function Login() {
return (
<Modal>
<h1>Iniciar sesión</h1>
{/* ... */}
</Modal>
)
}
Para asegurarse de que el contenido del modal no se renderice cuando no está activo, puede crear un archivo default.js
que devuelva null
.
export default function Default() {
return null
}
export default function Default() {
return null
}
Cerrar un modal
Si un modal se inició mediante navegación del cliente, por ejemplo usando <Link href="/login">
, puede cerrar el modal llamando a router.back()
o usando un componente Link
.
'use client'
import { useRouter } from 'next/navigation'
import { Modal } from 'components/modal'
export default async function Login() {
const router = useRouter()
return (
<Modal>
<span onClick={() => router.back()}>Cerrar modal</span>
<h1>Iniciar sesión</h1>
...
</Modal>
)
}
'use client'
import { useRouter } from 'next/navigation'
import { Modal } from 'components/modal'
export default async function Login() {
const router = useRouter()
return (
<Modal>
<span onClick={() => router.back()}>Cerrar modal</span>
<h1>Iniciar sesión</h1>
...
</Modal>
)
}
Más información sobre modales se cubre en la sección Rutas de intercepción.
Si desea navegar a otro lugar y cerrar un modal, también puede usar una ruta catch-all.

export default function CatchAll() {
return null
}
export default function CatchAll() {
return null
}
Las rutas catch-all tienen prioridad sobre
default.js
.
Rutas condicionales
Las rutas paralelas pueden usarse para implementar enrutamiento condicional. Por ejemplo, puede renderizar una ruta @dashboard
o @login
dependiendo del estado de autenticación.
import { getUser } from '@/lib/auth'
export default function Layout({
dashboard,
login,
}: {
dashboard: React.ReactNode
login: React.ReactNode
}) {
const isLoggedIn = getUser()
return isLoggedIn ? dashboard : login
}
import { getUser } from '@/lib/auth'
export default function Layout({ dashboard, login }) {
const isLoggedIn = getUser()
return isLoggedIn ? dashboard : login
}

Manejo de errores
Maneja errores en tiempo de ejecución envolviendo automáticamente segmentos de ruta y sus hijos en un Límite de Error (Error Boundary) de React.
Rutas de intercepción
Usa rutas de intercepción para cargar una nueva ruta dentro del diseño actual mientras enmascaras la URL del navegador, útil para patrones de enrutamiento avanzados como modales.