react-datatable
Concepts

Data loading

Data loading is the question of who owns the row set after the user changes the table.

The visible table can look the same in every mode. Search, filters, sorting, grouping, selection, preview, and display controls still belong to the table surface. What changes is where the final rows come from.

Local Data

Use local data when the browser can hold and transform the full working set.

<Datatable tableKey="customers" columns={columns} data={rows} getRowId={(row) => row.id} />

In this mode, the table receives rows through data and applies search, filters, sorting, and grouping in the browser.

This is the simplest model. It is a good fit for:

  • small and medium datasets
  • route loaders that already fetched the rows
  • tables where client-side filtering is enough
  • prototypes before the backend contract is final

Online Data

Use online data when the server owns the result set.

In this mode, the table turns its current state into a query and asks your backend for rows. The query includes the things users changed: filters, sorting, search, grouping, and navigation.

table state -> online query -> backend result -> visible rows

This is the right model when:

  • the dataset is too large for the browser
  • permissions must be enforced on the backend
  • totals, facets, or grouped results must match server truth
  • the table should load page by page or window by window

The table owns the interaction. Your backend owns which rows match.

Pagination and Infinite Scroll

Online mode still needs a navigation style.

Pagination gives users explicit pages. Use it for back-office workflows where totals, page size, and repeatable navigation matter.

Infinite scroll treats the result as one long sequence. Use it when the product should feel continuous and the user is browsing through many matching rows.

Both styles use the same table state. They only differ in how the next server window is requested.

Rendering Is Separate

Virtualization is not a data-loading mode.

Data loading decides which rows are available. Virtualization decides how many available rows are mounted in the DOM.

That means:

  • local tables can be virtualized
  • paginated tables can be virtualized
  • infinite tables can be virtualized
  • virtualization does not replace a backend query model

Keeping those ideas separate makes the API easier to reason about.

First Paint

If your route already loaded the first server result, pass it as initial online data. The table can use it for first paint as long as it matches the resolved table state.

This matters because saved views, persistence, and URL state can change the opening query. The table should not keep prefetched rows for the wrong filters or sorting.

Use This Rule

Choose the data mode by ownership:

  • browser owns the row set: use local data
  • server owns the row set: use online data
  • the question is DOM size, not row ownership: use virtualization

Next Steps

On this page