フロントエンド開発の先端を突っ走るNext.js
next.js アプリの初期化( npx create-next-app@latest <アプリ名> ) または pnpm create next-app@latest <アプリ名> または bun create next-app <アプリ名> )

next.js の 並列ルート(Parallel Routes)

並列ルート(Parallel Routes)

通常のJSX配置

export default function Layout({ children }) {
  return (
    <>
      <Sidebar />
      {children}
      <Modal />
    </>
  )
}

Parallel Routes での配置

export default function Layout({ children, sidebar, modal }) {
  return (
    <>
      {sidebar}
      {children}
      {modal}
    </>
  )
}

後者では app/@sidebar/page.tsxapp/@modal/page.tsx が独立してレンダリングされ、URLに応じて切り替わります

Parallel Routes で URL に応じて sidebar/children/modal を切り替えるサンプル

以下は @sidebar@modal スロットを使い、URL によって切り替える最小構成の例です。

フォルダ構成

app/
  layout.tsx
  page.tsx
  @sidebar/
    layout.tsx
    page.tsx
    default.tsx
  @modal/
    default.tsx
    photo/
      [id]/
        page.tsx
  dashboard/
    layout.tsx
    page.tsx
  photo/
    [id]/
      page.tsx

各ファイルの内容

app/layout.tsx

export default function Layout({ children, sidebar, modal }: {
  children: React.ReactNode
  sidebar: React.ReactNode
  modal: React.ReactNode
}) {
  return (
    <>
      {sidebar}
      <main>{children}</main>
      {modal}
    </>
  )
}

app/page.tsx

export default function HomePage() {
  return <p>Home</p>
}

app/@sidebar/layout.tsx

export default function SidebarLayout({ children }: { children: React.ReactNode }) {
  return <aside>{children}</aside>
}

app/@sidebar/page.tsx

export default function SidebarPage() {
  return <nav>Sidebar Nav</nav>
}

app/@sidebar/default.tsx

export default function SidebarDefault() {
  return <nav>Sidebar Default</nav>
}

app/@modal/default.tsx

export default function ModalDefault() {
  return null
}

app/@modal/photo/[id]/page.tsx

export default function PhotoModalPage({ params }: { params: { id: string } }) {
  return <div>Photo Modal: {params.id}</div>
}

app/dashboard/page.tsx

export default function DashboardPage() {
  return <p>Dashboard</p>
}

app/photo/[id]/page.tsx

export default function PhotoPage({ params }: { params: { id: string } }) {
  return <p>Photo Page: {params.id}</p>
}

URL ごとのレンダリング結果

URL children sidebar modal
/ Home Sidebar Nav null
/dashboard Dashboard Sidebar Nav null
/photo/123 Photo Page: 123 Sidebar Nav null
/dashboard(Intercepted)Dashboard Sidebar Nav Photo Modal: 123(Intercepted)

Intercepting Routes でモーダルを表示する例

app/dashboard/@modal/(..)photo/[id]/page.tsx を配置すると、/dashboard/photo/123 をインターセプトしてモーダル表示できます 1

Notes

  • Parallel Routes は App Router 専用です。Pages Router では利用できません。
  • default.tsx はスロットに対応するページがないときのフォールバックです 2
  • 実際のテスト例では sidebar prop を受け取る Layout が実装されています 3

Citations

File: docs/01-app/03-api-reference/03-file-conventions/intercepting-routes.mdx (L58-66)

### Modals

Intercepting Routes can be used together with [Parallel Routes](/docs/app/api-reference/file-conventions/parallel-routes) to create modals. This allows you to solve common challenges when building modals, such as:

- Making the modal content **shareable through a URL**.
- **Preserving context** when the page is refreshed, instead of closing the modal.
- **Closing the modal on backwards navigation** rather than going to the previous route.
- **Reopening the modal on forwards navigation**.

File: test/e2e/app-dir/parallel-routes-and-interception/app/parallel-side-bar/layout.tsx (L4-9)

export default function Layout({
  children,
  sidebar,
}: {
  children: React.ReactNode
  sidebar: React.ReactNode
No.2719
02/14 10:15

edit