Villkorad slot-rendering för instrumentpaneler och flikar
Styr instrumentpanelssektioner och flikvyer genom att mappa routens segment till parallella slots.
Villkorad slot-rendering för instrumentpaneler och flikar är en gratis lektion i Next.js 15 fullstack (App Router + Server Actions) på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Next.js 15 fullstack (App Router + Server Actions), och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Next.js 15 fullstack (App Router + Server Actions) innehåller totalt 4 lektioner.
Vad är parallella rutter?
Next.js 15 introducerar parallella rutter, en layoutprimitiv som låter er rendera flera sidor samtidigt i samma layout – var och en i sin egen namngivna slot.
Det passar utmärkt för instrumentpaneler där ni vill att oberoende sektioner, som en analyspanel, ett teamflöde och ett sidofält med aviseringar, ska läsas in samtidigt och oberoende av varandra.
- Slots definieras med mappkonventionen
@slotNameinuti ett layoutsegment - Varje slot skickas som en prop till den överordnade
layout.tsx - Slots renderas parallellt – en kan strömmas medan en annan redan är färdig
Tänk på slots som namngivna hål i layouten som routern fyller med olika delträd av rutter samtidigt.
Mappstruktur för parallella slots
För att skapa parallella slots placerar du mappar av typen @slotName direkt i mappen för ditt route-segment. Varje slot-mapp fungerar som ett eget litet route-träd.
En typisk dashboard kan se ut så här:
app/dashboard/layout.tsx— tar emot alla slot-propsapp/dashboard/@analytics/page.tsx— analytics-slotapp/dashboard/@team/page.tsx— slot för teamflödetapp/dashboard/@notifications/page.tsx— slot för aviseringar
Slot-mapparna påverkar inte URL:en. URL:en förblir /dashboard medan alla tre slots renderas samtidigt.
// File: app/dashboard/layout.tsx
// TypeScript interface showing slot props
interface DashboardLayoutProps {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
notifications: React.ReactNode;
}
export default function DashboardLayout({
children,
analytics,
team,
notifications,
}: 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>
<aside className="notifications-panel">{notifications}</aside>
</div>
);
}Standardfilen: hantera omatchade slots
När du navigerar till en URL som inte matchar en undersökväg för en slot behöver Next.js veta vad som ska renderas i den sloten. Utan en reservlösning skulle hela layouten misslyckas med en 404.
Lösningen är filen default.tsx i varje slot-mapp. Den fungerar som en reservrendering när sloten inte har någon aktiv matchning för den aktuella URL:en.
- Placera en
default.tsxi varje@slotName-mapp - Den kan returnera
nullför att inte rendera något, eller visa ett skelett/en platshållare - Detta gör att övriga slots fortsätter fungera även när en av dem saknar en aktiv undersökväg
// File: app/dashboard/@notifications/default.tsx
// Renders nothing when this slot has no active route match
export default function NotificationsDefault() {
return null;
}
// File: app/dashboard/@analytics/default.tsx
// Could render a skeleton instead
export default function AnalyticsDefault() {
return (
<div className="animate-pulse bg-gray-100 rounded-lg h-48" />
);
}Villkorlig slot-rendering med Server Components
Layoutkomponenten tar emot alla slots som props — vilket innebär att du kan använda villkorslogik direkt i layouten för att visa eller dölja slots baserat på data från servern, användarroller eller feature flags.
Eftersom layout.tsx som standard är en Server Component kan du hämta data asynkront direkt där för att fatta det här beslutet.
- Hämta den aktuella användarens roll från databasen eller sessionen
- Inkludera eller uteslut slot-props villkorligt från det som renderas
- Ingen JavaScript på klientsidan krävs för att styra synligheten
// File: app/dashboard/layout.tsx
import { getCurrentUser } from '@/lib/auth';
interface DashboardLayoutProps {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
}
export default async function DashboardLayout({
children,
analytics,
team,
}: DashboardLayoutProps) {
const user = await getCurrentUser();
const isAdmin = user?.role === 'admin';
return (
<div className="dashboard-grid">
<main>{children}</main>
{isAdmin && <aside>{analytics}</aside>}
<aside>{team}</aside>
</div>
);
}Bygg en dashboard med flikar och parallella routes
Parallella routes blir särskilt kraftfulla för flikbaserade gränssnitt. I stället för att använda state på klientsidan för att hålla reda på den aktiva fliken kopplar du varje flik till ett URL-segment, så att flikens state blir en del av URL:en.
Det här ger dig:
- Delbara URL:er — användare kan bokmärka en specifik flik
- Navigering mellan flikar med webbläsarens bakåt- och framåtknappar
- Oberoende laddningstillstånd för varje flik via Suspense
- Serverrenderat flikinnehåll utan hydreringskostnad för fliklogiken
Flikraden blir en uppsättning <Link>-komponenter som pekar på olika undersökvägar i sloten.
// File: app/dashboard/@tabs/layout.tsx
// Shared tab navigation rendered inside the @tabs slot
import Link from 'next/link';
interface TabsLayoutProps {
children: React.ReactNode;
}
export default function TabsLayout({ children }: TabsLayoutProps) {
return (
<div>
<nav className="flex gap-2 border-b mb-4">
<Link
href="/dashboard/overview"
className="tab-link"
>
Overview
</Link>
<Link
href="/dashboard/revenue"
className="tab-link"
>
Revenue
</Link>
<Link
href="/dashboard/users"
className="tab-link"
>
Users
</Link>
</nav>
<div className="tab-content">{children}</div>
</div>
);
}Koppla route-segment till fliksidor
Varje flik motsvarar en page.tsx-fil som ligger inuti sloten @tabs. URL-segmentet blir automatiskt väljare för den aktiva fliken — ingen JavaScript-state behövs.
För en dashboard på /dashboard med en @tabs-slot:
app/dashboard/@tabs/overview/page.tsx— aktiv på/dashboard/overviewapp/dashboard/@tabs/revenue/page.tsx— aktiv på/dashboard/revenueapp/dashboard/@tabs/users/page.tsx— aktiv på/dashboard/users
URL:en för den överordnade layout.tsx förblir densamma (/dashboard/*), medan endast innehållet i sloten @tabs uppdateras.
// File: app/dashboard/@tabs/revenue/page.tsx
import { getRevenueData } from '@/lib/data';
export default async function RevenueTab() {
const data = await getRevenueData();
return (
<section>
<h2 className="text-xl font-semibold mb-4">Revenue Overview</h2>
<dl className="grid grid-cols-3 gap-4">
<div>
<dt className="text-sm text-gray-500">Monthly Recurring</dt>
<dd className="text-2xl font-bold">
${data.mrr.toLocaleString()}
</dd>
</div>
<div>
<dt className="text-sm text-gray-500">Annual Run Rate</dt>
<dd className="text-2xl font-bold">
${data.arr.toLocaleString()}
</dd>
</div>
<div>
<dt className="text-sm text-gray-500">Churn Rate</dt>
<dd className="text-2xl font-bold">{data.churnRate}%</dd>
</div>
</dl>
</section>
);
}Markera den aktiva fliken med usePathname
För att visuellt visa vilken flik som är aktiv behöver du jämföra den aktuella URL:en med varje fliks href. Hooken usePathname() från next/navigation ger dig den aktuella sökvägen på klientsidan.
Eftersom flikraden behöver vara interaktiv (den läser den aktuella URL:en) måste den vara en Client Component. Du kan låta endast navigeringsfältet vara en Client Component och låta allt flikinnehåll förbli Server Components.
- Markera filen för fliknavigeringen med
'use client' - Använd
usePathname()för att identifiera det aktiva segmentet - Använd villkorliga klasser baserat på matchningen
'use client';
// File: app/dashboard/@tabs/_components/TabNav.tsx
import Link from 'next/link';
import { usePathname } from 'next/navigation';
const tabs = [
{ href: '/dashboard/overview', label: 'Overview' },
{ href: '/dashboard/revenue', label: 'Revenue' },
{ href: '/dashboard/users', label: 'Users' },
];
export function TabNav() {
const pathname = usePathname();
return (
<nav className="flex gap-1 border-b">
{tabs.map((tab) => {
const isActive = pathname === tab.href;
return (
<Link
key={tab.href}
href={tab.href}
className={`px-4 py-2 text-sm font-medium ${
isActive
? 'border-b-2 border-blue-600 text-blue-600'
: 'text-gray-500 hover:text-gray-700'
}`}
>
{tab.label}
</Link>
);
})}
</nav>
);
}Använd Suspense för oberoende laddning av slots
En av de största fördelarna med parallella slots är att varje slot strömmas separat. Du kan omge enskilda slots med <Suspense>-gränser så att en långsam slot inte hindrar en snabb slot från att renderas.
Detta eliminerar det klassiska dashboard-problemet där ett långsamt API-anrop fryser hela sidan.
- Omslut varje slot med en egen
<Suspense>i layouten - Varje slot visar sitt eget laddningsskelett medan den laddas
- Snabba slots visas direkt; långsamma slots strömmas in när de är klara
- Ingen
loading.tsxbehövs — Suspense ger dig detaljerad kontroll
// File: app/dashboard/layout.tsx
import { Suspense } from 'react';
import { AnalyticsSkeleton } from '@/components/skeletons';
interface DashboardLayoutProps {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
notifications: React.ReactNode;
}
export default function DashboardLayout({
children,
analytics,
team,
notifications,
}: DashboardLayoutProps) {
return (
<div className="grid grid-cols-3 gap-4">
<main className="col-span-2">
<Suspense fallback={<p>Loading main...</p>}>
{children}
</Suspense>
</main>
<div className="space-y-4">
<Suspense fallback={<AnalyticsSkeleton />}>
{analytics}
</Suspense>
<Suspense fallback={<p>Loading team...</p>}>
{team}
</Suspense>
<Suspense fallback={null}>
{notifications}
</Suspense>
</div>
</div>
);
}Villkorliga slots baserat på sökparametrar
Ibland vill du styra slotarnas synlighet med sökparametrar i stället för sökvägssegment — till exempel genom att växla en detaljpanel med ?panel=details.
I Server Components kan du komma åt sökparametrar via propen searchParams i page.tsx-filer, eller använda useSearchParams() i Client Components.
- Skicka
searchParamsvidare frånpage.tsxtill layouten eller använd en Server Action - Ta emot sökparametrar i layouten via sidans datalager i stället för direkt (layouter tar inte emot searchParams)
- Ett renare mönster är att använda slotens egen
page.tsxför att läsa searchParams och rendera innehåll villkorligt
// File: app/dashboard/@details/page.tsx
// Conditionally renders based on ?panel=details
interface DetailsPageProps {
searchParams: Promise<{ panel?: string }>;
}
export default async function DetailsPanel({
searchParams,
}: DetailsPageProps) {
const { panel } = await searchParams;
if (panel !== 'details') {
return null;
}
return (
<aside className="border-l pl-4">
<h3 className="font-semibold">Details Panel</h3>
<p className="text-sm text-gray-600">
Expanded details visible when ?panel=details is present.
</p>
</aside>
);
}Kombinera parallella routes med Server Actions för flikstate
Server Actions passar naturligt ihop med flikar i parallella routes. Du kan använda en Server Action för att ändra data direkt från en fliks sida och sedan låta Next.js validera om och rendera om endast den berörda sloten — inte hela sidan.
Detta skapar en sömlös UX: användaren skickar ett formulär i en flik, åtgärden körs på servern, sloten strömmas på nytt med färska data och alla andra slots lämnas orörda.
- Definiera Server Action med
'use server'i en separat fil eller inline - Anropa
revalidatePathellerrevalidateTagför att ogiltigförklara datacachen - Endast den relevanta sloten hämtar data på nytt och renderas om
// File: app/dashboard/@tabs/users/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';
export async function deactivateUser(userId: string): Promise<void> {
await db.user.update({
where: { id: userId },
data: { isActive: false },
});
// Only the users tab data is invalidated
revalidatePath('/dashboard/users');
}
// File: app/dashboard/@tabs/users/page.tsx (partial)
// import { deactivateUser } from './actions';
//
// <form action={deactivateUser.bind(null, user.id)}>
// <button type="submit">Deactivate</button>
// </form>Mjuk navigering och bevarande av slot-state
När du navigerar mellan flikar eller dashboard-sektioner med Next.js <Link> utför routern en mjuk navigering. Det innebär att:
- Endast slots vars route-segment har ändrats hämtas på nytt
- Slots med oförändrade routes behåller sitt befintliga renderade resultat och sitt React-state
- Scrollpositionen i opåverkade slots bevaras
Detta är en viktig fördel jämfört med traditionella flikimplementationer som använder state på klientsidan — du får URL-styrd navigering utan kostnaden för att rendera om hela sidträdet vid varje flikbyte.
Hård navigering (full omladdning av sidan) återställer alla slots, så använd alltid <Link> vid flikbyten i en dashboard med parallella routes.
Kunskapskontroll: omatchade slots
Du har en dashboard-layout med tre parallella slots: @analytics, @team och @notifications. En användare navigerar till /dashboard/settings, som är definierad under children men saknar motsvarande undersökväg i alla tre slot-mappar.
Vad händer med de tre slotarna, och vilken fil förhindrar ett 404-fel för hela layouten?
Sammanfattning: villkorlig slot-rendering för dashboards och flikar
I den här lektionen har du lärt dig att styra dashboard-sektioner och flikvyer med Next.js 15 Parallel Routes.
Viktiga lärdomar:
- Parallella slots använder mappkonventionen
@slotNameoch skickas som props till den överordnadelayout.tsx - En
default.tsxi varje slot-mapp krävs för att hantera omatchade URL:er och förhindra 404-fel - Layouten är en Server Component, så du kan styra slot-renderingen med asynkrona rollkontroller, feature flags eller andra serverdata
- Flikgränssnitt kopplar varje flik till ett URL-undersegment i en slot, vilket ger delbara, bokmärkningsbara och serverrenderade flikar utan overhead för state på klientsidan
- Omslut varje slot med en egen
<Suspense>-gräns så att långsamma slots inte hindrar snabba slots från att strömmas - Server Actions i fliksidor kan anropa
revalidatePathför att uppdatera endast den berörda sloten och lämna alla andra slots orörda - Mjuk navigering via
<Link>hämtar endast ändrade slots på nytt och bevarar React-state i de oförändrade
Parallella routes med villkorlig slot-logik ger dig en komponerbar, URL-styrd arkitektur för komplexa dashboards — helt utan en enda state-variabel på klientsidan för flikhantering.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Villkorad slot-rendering för instrumentpaneler och flikar” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Next.js 15 fullstack (App Router + Server Actions), inklusive ”Villkorad slot-rendering för instrumentpaneler och flikar”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Next.js 15 fullstack (App Router + Server Actions) innehåller totalt 4 lektioner.
Vad lär jag mig i ”Villkorad slot-rendering för instrumentpaneler och flikar”?
Styr instrumentpanelssektioner och flikvyer genom att mappa routens segment till parallella slots. Ni övar på Next.js 15 fullstack (App Router + Server Actions) med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Next.js 15 fullstack (App Router + Server Actions)?
Du behöver inga förkunskaper. Utbildningen i Next.js 15 fullstack (App Router + Server Actions) på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.
Hur lång tid tar lektionen ”Villkorad slot-rendering för instrumentpaneler och flikar”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Next.js 15 fullstack (App Router + Server Actions)-lektionen?
Ja. Varje Next.js 15 fullstack (App Router + Server Actions)-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Parallella routes med namngivna slots och standardsegment
- Intercepting routes för delade modalupplevelser
- Villkorad slot-rendering för instrumentpaneler och flikar
- Bygga ett foto-modalt flöde med mjuk navigering