0Pricing
Next.js 15 Fullstack (App Router + Server Actions) · Pelajaran

Rute Paralel dengan Slot Bernama dan Segmen Default

Render beberapa pohon rute independen secara bersamaan menggunakan konvensi @slot dan default.tsx.

Rute Paralel dengan Slot Bernama dan Segmen Default adalah pelajaran Next.js 15 Fullstack (App Router + Server Actions) gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Next.js 15 Fullstack (App Router + Server Actions), dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Next.js 15 Fullstack (App Router + Server Actions) mencakup 4 pelajaran total.

Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.

What Are Parallel Routes?

Parallel Routes is a Next.js App Router feature that lets you render multiple independent route segments simultaneously inside a single layout. Each segment lives in its own named slot and can navigate, load, and error independently.

  • Think of a dashboard with a sidebar, a main panel, and a notification feed — all loaded in parallel, each with its own loading/error states.
  • Parallel routes are defined using the @folder naming convention inside a route segment directory.
  • Each slot becomes a prop on the parent layout.tsx.

This is fundamentally different from nested layouts: parallel slots share the same URL but render separate route trees side by side.

The @slot Convention

To create a parallel slot, prefix a folder with @ inside any route segment. Next.js treats these as named slots rather than URL segments.

  • app/dashboard/@analytics/page.tsx → slot named analytics
  • app/dashboard/@team/page.tsx → slot named team
  • The @folder name does not appear in the URL — visiting /dashboard renders all matching slots.

A typical parallel-routes directory tree looks like this:

// Directory layout (not runnable — filesystem structure)
// app/
//   dashboard/
//     layout.tsx          <- receives @analytics and @team as props
//     page.tsx            <- default slot content (children)
//     @analytics/
//       page.tsx
//       loading.tsx
//     @team/
//       page.tsx
//       error.tsx

Writing the Parallel Layout

The parent layout.tsx receives each named slot as a React prop alongside the standard children prop. You can position them anywhere in the JSX.

  • TypeScript types for slots are just React.ReactNode.
  • Slots are completely independent — one can suspend while another is already rendered.
  • The children prop itself is an implicit slot named children.
// app/dashboard/layout.tsx
import React from 'react';

interface DashboardLayoutProps {
  children: React.ReactNode;
  analytics: React.ReactNode;
  team: React.ReactNode;
}

export default function DashboardLayout({
  children,
  analytics,
  team,
}: DashboardLayoutProps) {
  return (
    <div className="dashboard-grid">
      <main className="col-span-2">{children}</main>
      <aside className="analytics-panel">{analytics}</aside>
      <aside className="team-panel">{team}</aside>
    </div>
  );
}

Creating Slot Pages

Each named slot needs its own page.tsx. These pages are standard Server Components (or Client Components) — there is nothing special about their internal structure.

  • Slots can have their own loading.tsx, error.tsx, and nested routes.
  • Data fetching inside a slot is independent: one slot can await a slow database call without blocking the others.
// app/dashboard/@analytics/page.tsx
import { getAnalyticsSummary } from '@/lib/analytics';

export default async function AnalyticsSlot() {
  const summary = await getAnalyticsSummary();

  return (
    <section>
      <h2 className="text-lg font-semibold">Analytics</h2>
      <p>Total visits: <strong>{summary.totalVisits}</strong></p>
      <p>Conversion rate: <strong>{summary.conversionRate}%</strong></p>
    </section>
  );
}

// app/dashboard/@team/page.tsx
import { getTeamMembers } from '@/lib/team';

export default async function TeamSlot() {
  const members = await getTeamMembers();

  return (
    <ul>
      {members.map((m) => (
        <li key={m.id}>{m.name} — {m.role}</li>
      ))}
    </ul>
  );
}

Independent Loading States

Each slot can ship its own loading.tsx. Next.js wraps it in a Suspense boundary automatically, so slots stream in independently — fast slots appear immediately while slow ones show a skeleton.

  • This eliminates the waterfall problem common in single-tree layouts.
  • Users see meaningful UI much sooner because partial content renders first.
// app/dashboard/@analytics/loading.tsx
export default function AnalyticsLoading() {
  return (
    <div className="animate-pulse space-y-2">
      <div className="h-4 bg-gray-200 rounded w-1/2" />
      <div className="h-4 bg-gray-200 rounded w-3/4" />
      <div className="h-4 bg-gray-200 rounded w-2/3" />
    </div>
  );
}

// app/dashboard/@team/loading.tsx
export default function TeamLoading() {
  return (
    <ul className="space-y-2">
      {Array.from({ length: 4 }).map((_, i) => (
        <li key={i} className="h-4 bg-gray-200 rounded animate-pulse" />
      ))}
    </ul>
  );
}

The Problem: Soft Navigation and Missing Slots

Parallel routes shine during hard navigation (full page load), but soft navigation (client-side link clicks) reveals a problem.

When a user navigates to a sub-route — for example /dashboard/settings — Next.js looks for a matching page in every active slot. If a slot has no page for /settings, it becomes unmatched.

  • An unmatched slot does not simply disappear — Next.js needs to know what to render.
  • Without a fallback, Next.js renders a 404 for the entire page.
  • The solution is default.tsx.

Rescuing Unmatched Slots with default.tsx

default.tsx is the fallback file Next.js renders for a slot when it has no matching page.tsx for the current URL. It acts like a catch-all within the slot's subtree.

  • Place default.tsx at the root of each slot: @analytics/default.tsx.
  • During soft navigation to an unmatched sub-route, Next.js renders default.tsx instead of 404-ing.
  • default.tsx receives the same params as a page; you can use it to show the slot's normal content unchanged, or a meaningful placeholder.
// app/dashboard/@analytics/default.tsx
// Rendered when the current URL has no matching page in this slot.
import { getAnalyticsSummary } from '@/lib/analytics';

export default async function AnalyticsDefault() {
  // Reuse the same data as the main analytics page so the slot
  // stays visible during navigation to other sub-routes.
  const summary = await getAnalyticsSummary();

  return (
    <section>
      <h2 className="text-lg font-semibold">Analytics</h2>
      <p>Total visits: <strong>{summary.totalVisits}</strong></p>
    </section>
  );
}

default.tsx for the Root children Slot

The implicit children slot (i.e. page.tsx at the segment root) also needs a default.tsx when parallel slots are present. Without it, navigating to a named slot's sub-route that doesn't match children will 404.

  • Add app/dashboard/default.tsx alongside app/dashboard/page.tsx.
  • It typically re-renders the same content as page.tsx, or a neutral empty state.
// app/dashboard/default.tsx
// Fallback for the implicit 'children' slot during soft navigation.
export default function DashboardDefault() {
  return (
    <div>
      <h1 className="text-2xl font-bold">Dashboard</h1>
      <p className="text-gray-500">Select an item to get started.</p>
    </div>
  );
}

Nested Routes Inside Slots

Named slots support their own nested route hierarchies. You can add [id] dynamic segments, route groups, or additional layouts entirely inside a slot — all without affecting the URL segments of sibling slots.

  • Example: @analytics/chart/[chartId]/page.tsx renders at /dashboard/chart/42 only inside the analytics slot.
  • The parent layout and other slots remain untouched.
  • Each nested level inside a slot can have its own loading.tsx, error.tsx, and default.tsx.
// app/dashboard/@analytics/chart/[chartId]/page.tsx
interface Props {
  params: Promise<{ chartId: string }>;
}

export default async function ChartDetailPage({ params }: Props) {
  const { chartId } = await params;

  // In a real app, fetch chart data here
  return (
    <div>
      <h3>Chart #{chartId}</h3>
      <p>Detailed breakdown for chart {chartId}.</p>
    </div>
  );
}

// app/dashboard/@analytics/chart/[chartId]/default.tsx
export default function ChartDefault() {
  return <p className="text-sm text-gray-400">No chart selected.</p>;
}

Practical Pattern: Modal Alongside Page

A classic use-case for parallel routes is rendering a modal in one slot while the main content stays visible in another — without losing the current scroll position or unmounting components.

  • Create an @modal slot with a default.tsx that returns null (nothing visible by default).
  • When a user clicks a trigger, Next.js navigates to the modal's page, filling the slot.
  • The main children slot continues rendering unchanged.
// app/dashboard/@modal/default.tsx
// Renders nothing when no modal route is matched.
export default function ModalDefault() {
  return null;
}

// app/dashboard/@modal/user/[id]/page.tsx
interface Props {
  params: Promise<{ id: string }>;
}

export default async function UserModal({ params }: Props) {
  const { id } = await params;
  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center">
      <div className="bg-white rounded-lg p-6 w-96">
        <h2 className="text-xl font-bold">User #{id}</h2>
        <p>Profile details would appear here.</p>
      </div>
    </div>
  );
}

TypeScript Tip: Strongly-Typed Slot Props

As the number of slots grows, keep your layout props explicit with a dedicated TypeScript interface. This makes refactoring safer and IDE autocompletion more helpful.

  • Slot props are always React.ReactNode — they accept any renderable value Next.js injects.
  • You can combine parallel slots with searchParams or route params in the same layout signature.
  • For shared slot configuration (e.g. theming), pass context via a React Context Provider inside the layout rather than prop-drilling through each slot page.
// app/dashboard/layout.tsx — full typed version
import React from 'react';
import { DashboardNav } from '@/components/DashboardNav';

interface DashboardLayoutProps {
  children: React.ReactNode;   // implicit slot
  analytics: React.ReactNode;  // @analytics slot
  team: React.ReactNode;       // @team slot
  modal: React.ReactNode;      // @modal slot
  params: Promise<{ orgId: string }>;
}

export default async function DashboardLayout({
  children,
  analytics,
  team,
  modal,
  params,
}: DashboardLayoutProps) {
  const { orgId } = await params;

  return (
    <>
      <DashboardNav orgId={orgId} />
      <div className="grid grid-cols-3 gap-4 p-4">
        <div className="col-span-2">{children}</div>
        <div className="space-y-4">
          {analytics}
          {team}
        </div>
      </div>
      {modal}
    </>
  );
}

Knowledge Check: When Is default.tsx Required?

Test your understanding of the default.tsx file in parallel routes.

Recap: Parallel Routes with Named Slots and Default Segments

Here is what you learned in this lesson:

  • Parallel Routes let you render multiple independent route trees in the same layout simultaneously, each in its own @slot folder.
  • Named slots use the @folderName convention and become props (React.ReactNode) on the parent layout.tsx.
  • Each slot is truly independent: it can have its own loading.tsx, error.tsx, nested routes, and data fetching without blocking siblings.
  • default.tsx is the critical fallback file. Without it, soft navigation to a URL that does not match a slot produces a 404. Place a default.tsx in every slot — including the implicit children slot — to prevent this.
  • Common patterns include dashboard multi-panels (analytics + team side by side) and modal-alongside-page where the @modal slot's default.tsx returns null.
  • Keep layout props strongly typed with a TypeScript interface as the slot count grows.

With parallel routes and default.tsx in place, your layouts become resilient, independently streaming, and far easier to reason about than a single monolithic route tree.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Rute Paralel dengan Slot Bernama dan Segmen Default” gratis?

Ya — teks lengkap “Rute Paralel dengan Slot Bernama dan Segmen Default” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Next.js 15 Fullstack (App Router + Server Actions), upgrade ke CoddyKit PRO. Kursus Next.js 15 Fullstack (App Router + Server Actions) mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Rute Paralel dengan Slot Bernama dan Segmen Default”?

Render beberapa pohon rute independen secara bersamaan menggunakan konvensi @slot dan default.tsx. Kamu berlatih Next.js 15 Fullstack (App Router + Server Actions) dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Next.js 15 Fullstack (App Router + Server Actions)?

Tidak diperlukan pengalaman sebelumnya. Next.js 15 Fullstack (App Router + Server Actions) di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “Rute Paralel dengan Slot Bernama dan Segmen Default” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Next.js 15 Fullstack (App Router + Server Actions) ini?

Ya. Setiap pelajaran Next.js 15 Fullstack (App Router + Server Actions) menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Rute Paralel dengan Slot Bernama dan Segmen Default
  2. Rute Intersepsi untuk Pengalaman Modal Bersama
  3. Rendering Slot Bersyarat untuk Dasbor dan Tab
  4. Membangun Alur Modal Foto dengan Navigasi Lunak
← Kembali ke Next.js 15 Fullstack (App Router + Server Actions)