eduardweb.
App RouterAvansat#nextjs#ux#react#routing

Modaluri fără reîncărcare în Next.js App Router: Cum folosești corect Parallel și Intercepting Routes

De Elisabeta Stan, 26 iun. 2026 · 17 vizualizări · 3 like-uri

Postat 26 iun. 2026
typescript
import React from 'react';

interface LayoutProps {
  children: React.ReactNode;
  modal: React.ReactNode;
}

export default function RootLayout({
  children,
  modal,
}: LayoutProps) {
  return (
    <html lang="ro">
      <body>
        <main>{children}</main>
        {modal}
        <div id="modal-root" />
      </body>
    </html>
  );
}

Am implementat recent schema asta pe un site de portofoliu pentru un fotograf, unde aveam de încărcat rapid peste 4.000 de randări de înaltă rezoluție. Clientul voia ca utilizatorul să dea click pe o poză, să se deschidă un modal instant peste listă, dar dacă cineva dă refresh sau trimite link-ul unui prieten, să se încarce pagina dedicată, full-screen.

Să fim sinceri: prima dată când te uiți în documentația Next.js la secțiunea de Intercepting Routes, ai senzația că cineva de la Vercel a fumat ceva dubios când a gândit folder structure-ul. Simbolurile alea gen (.) sau (..) par scoase din regex-uri scrise la beție. Totuși, odată ce prinzi logica, schema funcționează brici și te scapă de zeci de linii de state management chinuit.

Structura de foldere (fără să-ți prinzi urechile)

Ideea de bază e că ai nevoie de un slot paralel (definit cu @) care va randa modalul doar când navigarea se face din interiorul aplicației (client-side transition).

Iată cum trebuie să organizezi folderele în app/:

  • app/@modal/(.)photos/[id]/page.tsx <- Modalul care interceptează ruta pe client-side.
  • app/photos/[id]/page.tsx <- Pagina clasică, accesată la refresh sau direct link.
  • app/layout.tsx <- Fișierul unde legăm cele două sloturi.

Punctul crucial este paranteza din (.)photos. Aceasta îi spune router-ului: „Când navighezi spre /photos/123, nu te duce la pagina normală, ci interceptează ruta și randează componenta asta în slotul @modal”.

Layout-ul: Unde se întâmplă magia

Pentru ca Next.js să știe unde să arunce modalul, trebuie să editezi layout.tsx din rădăcina rutei respective. Layout-ul trebuie să accepte slotul @modal ca prop, pe care îl randezi lângă {children}. Ai grijă să tratezi cazul în care slotul este gol (când nu ești pe o rută interceptată), caz în care Next.js are nevoie de un fișier default.tsx care returnează null în interiorul folderului @modal.

Trade-off-ul de care nu-ți zice nimeni în tutoriale

Metoda asta e genială pentru UX, dar vine la pachet cu niște bătăi de cap destul de mari.

În primul rând, închiderea modalului. Ca să închizi modalul și să te întorci la URL-ul anterior, trebuie să folosești router.back(). Am pățit ca pe ecrane de mobil, din cauza gesturilor de swipe back ale sistemului de operare, utilizatorul să fie aruncat complet în afara site-ului dacă intrase direct pe acea pagină.

În al doilea rând, starea de loading. La proiectul cu fotograful, am avut inițial un delay urât de 1.2 secunde la click pe poză pentru că pagina interceptată făcea fetch la date grele direct pe server. Ca să rezolv asta, am mutat fetch-ul pe client-side cu un skeleton instant în modal, lăsând server-side rendering-ul doar pentru pagina dedicată.

Voi cum gestionați problema asta? Ați rămas pe abordarea cu Parallel Routes sau preferați clasicul query param gen ?photoId=123 administrat manual?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.