React
Route parallele e slot nell'App Router
Gli slot `@nome` renderizzano pannelli indipendenti nella stessa pagina. Struttura, layout, il vincolo di `default.tsx` e i 404 che arrivano al refresh.
In sintesi
- Una cartella `@nome` è uno slot: non aggiunge segmenti all'URL.
- Il `layout` riceve gli slot come props, `children` compreso.
- Senza `default.tsx` una navigazione diretta sullo slot restituisce 404.
- Uno slot non è linkabile: il deep link passa dalla pagina o da una route intercettata.
Una route parallela è uno slot con nome: `@analytics` dentro `app/dashboard/` si renderizza nella stessa pagina, ma con il suo `loading.tsx` e il suo `error.tsx`. Serve per pannelli indipendenti e per modali che hanno un URL.
La struttura minima
app/
dashboard/
layout.tsx
page.tsx
@analytics/
page.tsx
loading.tsx
default.tsx
@team/
page.tsx
default.tsx
La cartella con la chiocciola non aggiunge un segmento all'URL: `/dashboard` resta `/dashboard`. Cambia solo il numero di cose che il `layout` riceve e può comporre.
Il layout riceve gli slot come props
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
analytics,
team,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
}) {
return (
{children}
{analytics}
{team}
);
}
`children` è lo slot implicito: la `page.tsx` della cartella. Gli altri slot hanno il nome della cartella, senza la chiocciola. Se non passi uno slot al layout, quel contenuto non compare e nessuno se ne accorge.
A cosa servono davvero
- Dashboard con pannelli che caricano a tempi diversi: ogni slot ha il suo confine di attesa.
- Modale con URL condivisibile, combinando lo slot con una route intercettata.
- Tab che mantengono lo stato quando l'utente cambia sezione.
- Due viste della stessa pagina, una per il team e una per il cliente, senza duplicare il layout.
Per lo stato attivo c'è `useSelectedLayoutSegment`, che accetta il nome dello slot. Funziona solo in un client component: sul server il segmento non esiste come hook.
// app/dashboard/@team/team-tabs.tsx
"use client";
import { useSelectedLayoutSegment } from "next/navigation";
export function TeamTabs() {
const segment = useSelectedLayoutSegment("team");
return {segment ?? "overview"};
}
Il vincolo che rompe i deploy
Ogni slot ha bisogno di un `default.tsx`, altrimenti una navigazione diretta a un URL che non matcha quello slot restituisce 404. La navigazione soft lo nasconde: il bug compare al refresh o al primo accesso da un link.
// app/dashboard/@analytics/default.tsx
export default function AnalyticsDefault() {
return null;
}
| File | Ruolo | Obbligatorio |
|---|---|---|
| `layout.tsx` | Riceve gli slot come props | Sì, per mostrarli |
| `@slot/page.tsx` | Contenuto dello slot | Sì, per quello slot |
| `@slot/default.tsx` | Fallback sulla navigazione diretta | Sì, se lo slot può non matchare |
| `@slot/loading.tsx` | Attesa indipendente | No, ma è il motivo per usarlo |
Il numero che conta
Il catalogo EneUI indicizza 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati il 1 novembre 2026 su `/api/stats`. Per comporre gli slot servono tre categorie: tabs, blocchi dashboard e modal.
Lo slot eredita i confini di attesa: leggi streaming e Suspense nell'App Router. Per il fallimento isolato c'è error boundary nell'App Router. Per la struttura generale la struttura di un progetto App Router. Per il confronto con un altro framework Astro vs Next.js.
Limite noto: uno slot non è una route. Non puoi linkare `/dashboard/@analytics`, e non puoi annidare uno slot dentro un altro slot oltre il livello del layout che li dichiara.
Domande frequenti
Una route parallela cambia l'URL?
No. La chiocciola nella cartella indica uno slot, non un segmento. `/dashboard` resta lo stesso URL con o senza `@analytics`.
Perché al refresh ottengo 404?
Manca il `default.tsx` dello slot. In navigazione soft il componente resta montato, ma al refresh Next.js deve riempire lo slot e non trova un fallback.
Posso usare gli slot per i modali?
Sì, insieme a una route intercettata come `(.)photo/[id]`. Lo slot mostra il modale e la pagina sottostante resta montata.
Gli slot condividono il data fetching?
No. Ogni slot renderizza il proprio albero con le proprie fetch. Se due slot leggono lo stesso dato, React non lo deduplica tra loro.
Quanti slot posso avere?
Quanti ne vuoi nello stesso layout, purché i nomi siano unici. Oltre tre o quattro il layout diventa difficile da leggere.