eduardweb.
shadcn/uiAvansat#nextjs#react#shadcn-ui#tanstack-table

Cum am implementat server-side pagination și filtrare cu shadcn/ui în Next.js

De Diana Oprea, 2 iun. 2026 · 1 vizualizări · 2 like-uri

Postat 2 iun. 2026
typescript
export function useServerTable({ pageParam = 'page', limitParam = 'limit' }) {
  const router = useRouter();
  const searchParams = useSearchParams();

  const page = Number(searchParams.get(pageParam)) || 1;
  const limit = Number(searchParams.get(limitParam)) || 10;

  const handlePaginationChange = (updaterOrValue: any) => {
    const nextState = typeof updaterOrValue === 'function' 
      ? updaterOrValue({ pageIndex: page - 1, pageSize: limit }) 
      : updaterOrValue;

    const params = new URLSearchParams(searchParams.toString());
    params.set(pageParam, String(nextState.pageIndex + 1));
    params.set(limitParam, String(nextState.pageSize));

    router.push(`?${params.toString()}`, { scroll: false });
  };

  return { page, limit, handlePaginationChange };
}

Dacă ai folosit componenta de Table din shadcn/ui, probabil ai observat că toate exemplele lor din documentație sunt pe client-side. Când treci de 10.000 de rânduri în baza de date, browserul începe să gâfâie și ai nevoie rapid de server-side pagination, sorting și filtering. Am pățit asta pe un proiect recent unde aveam vreo 45.000 de înregistrări și clientul voia timpi de încărcare sub o secundă; inițial încărcam totul în pagină și browserul pur și simplu îngheța timp de 3 secunde.

Soluția corectă în Next.js (App Router) este să muți totul pe server și să folosești URL-ul ca single source of truth. Adică, în loc să ții starea tabelului în useState, o citești direct din searchParams.

De ce useState în tabel e o idee proastă pe server-side

Când folosești starea internă a TanStack Table (sorting, pagination), pierzi capacitatea de a da copy-paste la link. Dacă un coleg din suport vrea să trimită un link către pagina 4, filtrată după statusul "Active", nu poate dacă starea e doar locală.

Soluția pe care am mers eu folosește search params din Next.js pentru a controla starea tabelului. Când userul dă click pe pagină, facem un update în URL, Next.js re-mandează pagina de pe server cu noile date din baza de date, iar tabelul se randează corect din prima.

Cum legăm TanStack Table de URL

Trebuie să dezactivăm managementul intern de stare al TanStack pentru paginare și sortare și să îi spunem manual ce valori să afișeze. Folosim pageCount calculat pe server și trimis ca prop.

Pentru asta, definim manual proprietățile pageCount, state (unde pasăm valorile parsate din URL) și funcțiile de callback precum onPaginationChange sau onSortingChange. În loc de setere clasice de React, declanșăm o navigare prin router.push cu noul query string.

Un trade-off sincer pe care trebuie să îl știi

Abordarea asta e excelentă pentru SEO, bookmarking și performanță de randare pe client. Însă vine cu un cost. Fiecare schimbare de pagină sau sortare declanșează un request pe server. Dacă baza ta de date nu are indecși puși cum trebuie pe coloanele de sortare, utilizatorul va simți un lag vizibil la fiecare click.

La proiectul meu, am economisit cam 30% la build time și primul load eliminând tonele de JS necesare pentru filtrarea pe client, dar a trebuit să punem un debounce serios de vreo 400ms pe inputul de search ca să nu bombardăm baza de date la fiecare tastă apăsată.

Cum gestionați voi stările astea complexe în Next.js? Mergeți pe URL search params sau preferați să trageți datele prin API routes cu un client-side fetcher ca SWR sau React Query?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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