Next.js data grid

A data grid for Next.js and the App Router

Fetch the rows in a Server Component, render the grid in a Client Component, and ship it. The grid renders its column headers and skeleton on the server, sorts and filters large data in a Web Worker it starts itself, and needs no extra build configuration.

Everything on this page is in the free Community edition (@kanunilabs/datagrid-react).

One client boundary

The grid holds state, so the file that renders it starts with "use client". Fetch the rows in a Server Component and pass them down as a prop; only the grid itself is client code.

No worker file to copy

Above roughly 20,000 rows the grid moves filtering and sorting into a Web Worker. The worker is compiled into the package and started from a Blob URL, so Next never has to resolve a worker file from node_modules, and nothing goes into public/.

Server-rendered markup

The server render outputs the grid frame and the column headers, so the page is not an empty box before hydration; rows arrive with the client.

App Router: server data, client grid

// app/sales/SalesGrid.tsx
'use client';

import { DataGrid, type ReactGridColumnDef } from '@kanunilabs/datagrid-react';
import '@kanunilabs/datagrid-react/styles.css';

type Sale = { id: number; product: string; revenue: number };

const columns: ReactGridColumnDef<Sale>[] = [
  { field: 'product', headerName: 'Product', width: 220 },
  { field: 'revenue', headerName: 'Revenue', dataType: 'number', width: 140 },
];

export function SalesGrid({ rows }: { rows: Sale[] }) {
  return <DataGrid gridId="sales" dataSource={rows} rowKey="id" columns={columns} style={{ height: 500 }} />;
}

// app/sales/page.tsx (a Server Component)
import { SalesGrid } from './SalesGrid';

export default async function SalesPage() {
  const rows = await getSales(); // your data access
  return <SalesGrid rows={rows} />;
}

Every option: SSR and bundlers guide.

Questions

Do I need dynamic(() => import(...), { ssr: false })?
Not for the DataGrid: it renders on the server as markup and becomes interactive on the client. Mark the file that renders it with "use client".
Can the rows come from an API instead?
Yes, and that is free too: with a server-side data source the grid asks your endpoint for the rows in view as the user scrolls, and filtering, sorting and totals run on your server.
What about the pivot table?
The PivotGrid has its own Next.js page: it is loaded client-side only, and the worker needs no setup either.

Related