eduardweb.
App RouterAvansat#nextjs#ux#react#app-router

Cum faci un modal pe /photos/[id] fără reload folosind Parallel și Intercepting Routes în Next.js

De Vlad Stancu, 21 iun. 2026 · 19 vizualizări · 2 like-uri

Postat 21 iun. 2026
typescript
// app/layout.tsx
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 className="container mx-auto">
          {children}
        </main>
        {/* Slotul pentru modal va fi randat doar când ruta este interceptată */}
        {modal}
      </body>
    </html>
  );
}

Să fim serioși, modalurile clasice care strică URL-ul sau cele care cer un refresh complet al paginii sunt istorie. Astăzi vorbim despre cum faci un modal de detalii (gen cel de pe Instagram sau Unsplash) folosind Parallel și Intercepting Routes în Next.js, fără să pierzi contextul paginii din spate.

Am implementat schema asta recent la un portofoliu cu vreo 12.000 de imagini indexate. UX-ul este pur și simplu genial: userul dă click pe o poză din listă, se deschide modalul instant, URL-ul din browser se schimbă în /photos/123, dar pagina din spate rămâne intactă. Partea cea mai mișto? Dacă cineva dă refresh sau trimite link-ul unui prieten, se încarcă direct pagina de detalii full-screen, nu modalul peste listă.

Cum funcționează magia asta?

Next.js ne pune la dispoziție două concepte din App Router: sloturile (Parallel Routes, mapate cu @) și intercepările (Intercepting Routes, mapate cu (..)).

Structura de directoare este de obicei piatra de încercare. Dacă ai greșit un singur caracter, Next.js îți va da o eroare 404 silențioasă sau va ignora complet ruta. Structura corectă arată așa:

app/
├── @modal/
│   ├── (..)photos/
│   │   └── [id]/
│   │       └── page.tsx  <- Aici randezi modalul tău
│   └── default.tsx       <- Returnează null (esențial!)
├── photos/
│   └── [id]/
│       └── page.tsx      <- Pagina full-screen (pentru direct access)
├── layout.tsx            <- Primește children și modal ca props
└── page.tsx              <- Pagina principală cu lista de imagini

Când userul navighează de pe / către /photos/12, Next.js interceptează ruta (datorită folderului (..)photos) și o randează în interiorul slotului @modal. URL-ul se schimbă, dar layout-ul principal nu se demontează.

Trade-off-uri sincere (ce nu scrie în documentație)

Arată spectaculos, dar vine la pachet cu niște dureri de cap majore pe care le-am simțit pe pielea mea.

În primul rând, debug-ul e destul de greoi. Dacă ai probleme cu stările sau cu cache-ul routerului client-side, te vei trezi că modalul rămâne agățat pe ecran chiar și după ce navighezi în altă parte.

În al doilea rând, managementul de state global devine ciudat. Dacă ai nevoie ca acțiunile din modal (de exemplu, un buton de Like) să se reflecte imediat în lista din spate, trebuie să te bazezi pe un state manager comun (Zustand, React Context) sau să forțezi o invalidare de router cu router.refresh(), ceea ce poate adăuga lag inutil.

Un alt detaliu pe care mulți îl uită: fișierul default.tsx. Dacă nu îl pui în rădăcina slotului tău (@modal), Next.js o să arunce 404 când userul face un hard refresh pe o altă pagină a site-ului care nu are modalul activ. De ce? Pentru că routerul încearcă să randeze slotul @modal pe noua pagină și, negăsind o potrivire implicită, crapă.

Concluzia mea

Merită efortul? Da, absolut, dar doar dacă UX-ul este o prioritate critică pentru proiectul tău (cum e la e-commerce sau platforme media). Dacă ai nevoie doar de un simplu modal de confirmare sau setări, folosește clasicul ?modal=true în query params sau un state local în React. Îți vei salva mulți neuroni.

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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