並列ルート
パラレルルートを使用すると、同じレイアウト内で複数のページを同時に、または条件付きでレンダリングできます。これは、ダッシュボードやソーシャルサイトのフィードなど、アプリの高度に動的なセクションに役立ちます。
たとえば、ダッシュボードを考慮すると、パラレルルートを使用して team と analytics のページを同時にレンダリングできます。

規約
スロット
パラレルルートは、名前付きのスロットを使用して作成されます。スロットは @folder という規約で定義されます。たとえば、次のファイル構造は 2 つのスロット: @analytics と @team を定義します。

スロットは、親レイアウトにプロパティとして渡されます。上記の例では、app/layout.js のコンポーネントは @analytics と @team のスロットプロパティを受け入れ、それらを children プロパティと並行してレンダリングできます。
export default function Layout({
children,
team,
analytics,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{children}
{team}
{analytics}
</>
)
}ただし、スロットはルートセグメントではなく、URL構造には影響しません。たとえば、/@analytics/views の場合、@analytics はスロットであるため、URL は /views になります。スロットは、通常の Page コンポーネントと組み合わせて、ルートセグメントに関連付けられた最終的なページを形成します。このため、同じルートセグメントレベルで 静的 スロットと 動的 スロットを個別に持つことはできません。いずれか 1 つのスロットが動的な場合、そのレベルのすべてスロットは動的である必要があります。
知っておくと良いこと:
childrenプロパティは、フォルダにマッピングする必要のない暗黙的なスロットです。これは、app/page.jsがapp/@children/page.jsと同等であることを意味します。
default.js
default.js ファイルを定義して、初回ロードまたはフルページリロード中に、一致しないスロットのフォールバックとしてレンダリングできます。
次のフォルダ構造を検討してください。@team スロットには /settings ページがありますが、@analytics にはありません。

/settings に移動すると、@team スロットは /settings ページをレンダリングし、@analytics スロットの現在アクティブなページを維持します。
リフレッシュすると、Next.js は @analytics の default.js をレンダリングします。default.js が存在しない場合は、404 がレンダリングされます。
さらに、children は暗黙的なスロットであるため、Next.js が親ページの有効な状態を回復できない場合に children のフォールバックをレンダリングするために default.js ファイルを作成する必要があります。
動作
デフォルトでは、Next.js は各スロットの有効な*状態*(またはサブページ)を追跡します。ただし、スロット内でレンダリングされるコンテンツは、ナビゲーションの種類によって異なります。
- ソフトナビゲーション: クライアントサイドナビゲーション中、Next.js は 部分的なレンダリング を実行し、スロット内のサブページを変更しながら、URL と一致しない場合でも、他のスロットの有効なサブページを維持します。
- ハードナビゲーション: フルページロード(ブラウザのリフレッシュ)後、Next.js は URL と一致しないスロットの有効な状態を判断できません。代わりに、一致しないスロットの
default.jsファイルをレンダリングするか、default.jsが存在しない場合は404をレンダリングします。
知っておくと良いこと:
- 一致しないルートの
404は、意図しないページにパラレルルートを誤ってレンダリングしないようにするのに役立ちます。
例
useSelectedLayoutSegment(s) を使用
useSelectedLayoutSegment と useSelectedLayoutSegments の両方に parallelRoutesKey パラメータがあり、スロット内のアクティブなルートセグメントを読み取ることができます。
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function Layout({ auth }: { auth: React.ReactNode }) {
const loginSegment = useSelectedLayoutSegment('auth')
// ...
}ユーザーが app/@auth/login (または URL バーの /login)に移動すると、loginSegment は文字列 "login" と等しくなります。
条件付きルート
パラレルルートを使用して、ユーザーロールなどの特定の条件に基づいてルートを条件付きでレンダリングできます。たとえば、/admin または /user ロールに対して異なるダッシュボードページをレンダリングする場合。

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
}タブグループ
スロット内に layout を追加することで、ユーザーがスロットを独立してナビゲートできるようになります。これはタブの作成に役立ちます。
たとえば、@analytics スロットには 2 つのサブページがあります: /page-views と /visitors。

@analytics 内で、layout ファイルを作成して、2 つのページ間でタブを共有します。
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<nav>
<Link href="/page-views">Page Views</Link>
<Link href="/visitors">Visitors</Link>
</nav>
<div>{children}</div>
</>
)
}モーダル
パラレルルートは、インターセプトルートと組み合わせて、ディープリンクをサポートするモーダルを作成できます。これにより、モーダルの構築時に一般的な課題を解決できます。
- モーダルコンテンツを**URL経由で共有可能**にする。
- ページがリフレッシュされたときに、モーダルが閉じるのではなく、**コンテキストを維持**する。
- 後方ナビゲーション時に、前のルートに移動するのではなく、**モーダルを閉じる**。
- 前方ナビゲーション時にモーダルを再度開く.
ユーザーがクライアントサイドナビゲーションを使用してレイアウトからログインモーダルを開くか、個別の /login ページにアクセスできる UI パターンを検討してください。

このパターンを実装するには、まず**メイン**ログインページをレンダリングする /login ルートを作成します。

import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}次に、@auth スロット内に、null を返す default.js ファイルを追加します。これにより、アクティブでないときにモーダルがレンダリングされないようになります。
export default function Default() {
return null
}@auth スロット内で、/login ルートをインターセプトするには、<Modal> コンポーネントとその子を @auth/(.)login/page.tsx ファイルにインポートし、フォルダ名を /@auth/(.)login/page.tsx に更新します。
import { Modal } from '@/app/ui/modal'
import { Login } from '@/app/ui/login'
export default function Page() {
return (
<Modal>
<Login />
</Modal>
)
}知っておくと良いこと
(.)という規約は、ルートのインターセプトに使用されます。詳細については、インターセプトルートのドキュメントを参照してください。<Modal>の機能をモーダルコンテンツ(<Login>)から分離することで、モーダル内のコンテンツ(例: フォーム)がサーバーコンポーネントであることを保証できます。詳細については、クライアントコンポーネントとサーバーコンポーネントのインターリーブを参照してください。
モーダルを開く
これで、Next.js ルーターを活用してモーダルを開閉できます。これにより、モーダルが開いているときに URL が正しく更新され、後方および前方にナビゲートするときにも同様に更新されます。
モーダルを開くには、@auth スロットを親レイアウトにプロパティとして渡し、children プロパティと一緒にレンダリングします。
import Link from 'next/link'
export default function Layout({
auth,
children,
}: {
auth: React.ReactNode
children: React.ReactNode
}) {
return (
<>
<nav>
<Link href="/login">Open modal</Link>
</nav>
<div>{auth}</div>
<div>{children}</div>
</>
)
}ユーザーが <Link> をクリックすると、/login ページにナビゲートする代わりにモーダルが開きます。ただし、リフレッシュまたは初回ロード時に /login にナビゲートすると、ユーザーはメインのログインページに移動します。
モーダルを閉じる
router.back() を呼び出すか、Link コンポーネントを使用することでモーダルを閉じることができます。
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }: { children: React.ReactNode }) {
const router = useRouter()
return (
<>
<button
onClick={() => {
router.back()
}}
>
Close modal
</button>
<div>{children}</div>
</>
)
}@auth スロットをレンダリングする必要がなくなったページにナビゲートするために Link コンポーネントを使用する場合、パラレルルートが null を返すコンポーネントに一致することを確認する必要があります。たとえば、ルートページに戻るときは、@auth/page.tsx コンポーネントを作成します。
import Link from 'next/link'
export function Modal({ children }: { children: React.ReactNode }) {
return (
<>
<Link href="/">Close modal</Link>
<div>{children}</div>
</>
)
}export default function Page() {
return null
}または、他のページ(/foo、/foo/bar など)にナビゲートする場合は、キャッチオールスロットを使用できます。
export default function CatchAll() {
return null
}知っておくと良いこと
- パラレルルートの動作により、
@authスロットでキャッチオールルートを使用します。スロットに一致しなくなったルートへのクライアントサイドナビゲーションは表示されたままになるため、モーダルを閉じるためにnullを返すルートにスロットを一致させる必要があります。- その他の例としては、ギャラリーで写真モーダルを開きながら、専用の
/photo/[id]ページを持つこと、またはサイドモーダルでショッピングカートを開くことなどが挙げられます。- インターセプトおよびパラレルルートを使用したモーダルの例を表示する。
ローディングとエラーUI
パラレルルートは独立してストリームできるため、各ルートの独立したエラーおよびローディング状態を定義できます。

役に立ちましたか?







