Capítulo 124 de 456

Parallel Routes

Core Idea

Renderiza uma ou mais páginas simultaneamente (ou condicionalmente) dentro do mesmo layout, usando "slots" nomeados. Útil para dashboards, feeds e modais com deep linking.

Key Concepts

  • Slot (@folder): convenção que cria uma prop nomeada no layout pai; não é um route segment e não afeta a URL.
  • children como slot implícito: app/page.js equivale a app/@children/page.js.
  • default.js: fallback renderizado para um slot não correspondido em hard navigation (refresh/load inicial); sem ele, Next.js renderiza 404.
  • Soft vs Hard Navigation: navegação client-side preserva o subpage ativo de cada slot mesmo sem match com a URL; hard navigation exige default.js para slots não correspondidos.
  • Restrição de rendering: se um slot é dinâmico, todos os slots daquele nível de rota precisam ser dinâmicos (não há mistura prerendered/dynamic no mesmo nível).

Code Examples

export default function Layout({
  children,
  team,
  analytics,
}: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <>
      {children}
      {team}
      {analytics}
    </>
  )
}
  • O que demonstra: slots @team e @analytics chegam como props ao layout e renderizam ao lado de children.
import { checkUserRole } from '@/lib/auth'

export default function Layout({
  user,
  admin,
}: {
  user: React.ReactNode
  admin: React.ReactNode
}) {
  const role = checkUserRole()
  return role === 'admin' ? admin : user
}
  • O que demonstra: renderização condicional por role; ambos os slots executam suas fetches no servidor mesmo que só um seja retornado, exigindo autorização dentro de cada slot/DAL.

Anti-patterns

  • Confiar na condicional do layout como autorização: @admin/page.js roda e busca dados para todo usuário, independente do que o layout retorna; autorize dentro da página ou na Data Access Layer.
  • Usar Link para fechar modal sem slot de fallback: navegação client-side para rota não correspondida mantém o slot visível; é preciso um @auth/page.tsx (ou catch-all [...catchAll]) retornando null.
  • Esquecer default.js para children: mesmo sendo slot implícito, ele também precisa de fallback quando Next.js não recupera o estado ativo do pai.

Key Takeaways

  1. Combine Parallel Routes com Intercepting Routes ((.)login) para modais com deep link, share via URL e navegação back/forward corretas.
  2. Feche modal com router.back() dentro de um Client Component, ou com Link apontando para uma rota que resolve o slot a null.
  3. Use useSelectedLayoutSegment('slotName') para ler o segmento ativo dentro de um slot específico.
  4. Um layout.js dentro de um slot permite navegação independente (ex.: tabs) sem afetar outros slots.

Connects To

  • Intercepting Routes: par natural para construir modais com URL própria.
  • loading.js / error.js: cada slot pode ter estados de loading/erro independentes via streaming.