React
Tabella shadcn con TanStack Table
TanStack Table gestisce ordinamento e filtri, i componenti Table disegnano il markup. La versione 9 ha cambiato API: useTable sostituisce useReactTable.
In sintesi
- TanStack Table è headless: non genera markup, quindi il markup resta dei componenti Table di shadcn.
- Dalla 9.3.1 l'API è useTable con tableFeatures; useReactTable è sostituito da useLegacyTable.
- Il pacchetto pesa 122.555 byte non compressi e ha licenza MIT.
Risposta breve: monta i componenti Table di shadcn e passa dati e colonne a TanStack Table, che gestisce ordinamento, filtri e paginazione senza generare markup. La tabella resta tua, la logica no.
Le colonne
import {
createSortedRowModel,
rowSortingFeature,
sortFns,
tableFeatures,
} from "@tanstack/react-table";
import type { ColumnDef } from "@tanstack/react-table";
type Invoice = { id: string; total: number };
const features = tableFeatures({
rowSortingFeature,
sortedRowModel: createSortedRowModel(),
sortFns,
});
export const columns: Array> = [
{ accessorKey: "id", header: "Fattura" },
{
accessorKey: "total",
header: "Totale",
cell: (info) => info.getValue().toFixed(2) + " EUR",
},
];
Le feature sono opt-in: tableFeatures riceve solo ciò che usi, quindi ordinamento, filtri e paginazione non entrano nel bundle se non li dichiari. Il core row model c'è sempre, gli altri row model si registrano come slot.
La tabella
import { useTable } from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { columns, features } from "./columns";
export function InvoiceTable({ data }: { data: Array }) {
const table = useTable({ key: "invoices", features, columns, data });
return (
{table.getHeaderGroups().map((group) => (
{group.headers.map((header) => (
{header.isPlaceholder ? null : }
))}
))}
{table.getRowModel().rows.map((row) => (
{row.getAllCells().map((cell) => (
))}
))}
);
}
Il metodo getToggleSortingHandler arriva dalla feature di ordinamento appena registrata: senza quella riga in tableFeatures il click non cambia nulla. FlexRender disegna la cella con la funzione che hai scritto nella colonna, oppure stampa il valore.
Perché due livelli
Il vantaggio è la separazione: TanStack non sa cosa sia un tr, shadcn non sa cosa sia un ordinamento. Puoi cambiare il markup senza riscrivere la logica, o sostituire il markup con una lista su mobile, e i due pezzi continuano a funzionare.
Il comando
npm install @tanstack/react-table@9
npx shadcn@latest add table
Record vivi nel catalogo
Tre record mostrano il risultato: la libreria shadcn, il blocco table-01 con intestazioni e paginazione, e la categoria blocchi tabella. La licenza è indicata su ogni pagina.
La limitazione
Il pacchetto non virtualizza: una tabella con mille righe monta mille nodi, e per alleggerirla serve TanStack Virtual, un altro pacchetto MIT. Inoltre l'ordinamento client-side lavora sui dati già scaricati; con diecimila righe la paginazione deve passare dal server, altrimenti il costo si sposta solo nella rete.
Dove continuare
Il modello di distribuzione è in che cos'è shadcn/ui; l'errore più comune con flexRender è in TanStack Table e flexRender; il confronto fra librerie è in librerie di tabelle React.
Domande frequenti
Perché useReactTable non esiste più?
Perché la versione 9 espone useTable con tableFeatures. L'API precedente resta disponibile dall'export legacy del pacchetto, con useLegacyTable al posto di useReactTable.
TanStack Table genera la tabella?
No, è headless: restituisce stato e funzioni, il markup lo scrivi tu. Con shadcn usi i componenti Table, TableRow e TableCell, quindi lo stile resta quello del design system.
Come aggiungo i filtri?
Registri la feature di filtering e il row model filtrato in tableFeatures, poi colleghi un input a column.setFilterValue. Senza la registrazione l'API di filtro non esiste sul tavolo.
Funziona con dati caricati dal server?
Sì, in modalità manuale: passi le righe della pagina corrente e lasci che ordinamento e paginazione siano parametri della richiesta. Le funzioni getSortedRowModel e getPaginationRowModel non servono in quel caso.
Meglio TanStack Table o i componenti Table di shadcn da soli?
I componenti Table bastano per una tabella statica di poche righe. TanStack Table serve quando arrivano ordinamento, filtri, selezione o paginazione, perché quella logica scritta a mano diventa presto uno stato duplicato.