react-datatable
Guides

Add URL sync

Add URL sync when the URL is part of the product surface, not just a convenient way to share a one-off state.

This is the right tool for pages where people expect refresh, back/forward navigation, or a pasted URL to preserve the active query state.

When to use URL sync

Use continuous URL sync when people need to:

  • reload the page and keep the same search, filters, sorting, or grouping
  • use back and forward navigation as part of the table workflow
  • bookmark a live working state
  • treat table state as part of the page's contract

Do not reach for it by default.

For many product tables, persistState plus copyLink is a better fit because it keeps the address bar stable during normal interaction.

Turn on URL sync

<Datatable
  tableKey="customers"
  data={rows}
  columns={columns}
  getRowId={(row) => row.id}
  urlSync={{
    enabled: true,
    acceptUrlParams: true,
    historyMode: "replace",
  }}
/>

The table reads URL state during initialization, merges it through the table-state coordinator, and then enables continuous store-to-URL sync after it is ready.

History behavior

historyMode controls how state changes affect browser navigation.

  • Use "replace" when the page should reflect the latest state without creating a long back-stack trail.
  • Use "push" when stepping backward through prior table states is a real product behavior.

If you are unsure, start with "replace".

What URL sync includes

URL sync serializes the shareable query state of the table:

  • global search (q)
  • column filters (f.columnId)
  • sorting (s)
  • filter mode (fm)
  • grouping (g)

It does not serialize personal layout preferences such as column visibility, widths, order, sticky columns, or the active saved-view ID.

Those belong in persistence and saved-view systems instead.

Initialization priority

URL state has the highest priority during initialization.

A URL-synced state can override:

  • default store state
  • persisted per-user state
  • initialState
  • saved default views
  • current-view persistence

That precedence makes pasted links and bookmarks reliable.

One-load URL params

If the page should accept shared URLs but should not keep mutating the address bar after load, use this pattern instead:

<Datatable
  tableKey="customers"
  data={rows}
  columns={columns}
  getRowId={(row) => row.id}
  urlSync={{
    enabled: false,
    acceptUrlParams: true,
  }}
  toolbar={{ copyLink: true }}
/>

In that mode, the table reads the incoming URL state once, applies it, and clears the datatable params afterward.

That is usually better for product tables where the address bar should stay clean but shared links should still work.

Long filter states

The URL writer uses the table's canonical filter encoding:

  • text and number filters use their condition mode names
  • date filters use preset, range, before, after, and custom
  • list filters use include and exclude

Continuous URL sync works best when filters are reasonably compact and the page is not trying to encode large custom payloads into the URL.

If users routinely build large states, guide them toward saved views instead.

Multi-table pages

Only one table on a page should run with urlSync.enabled: true.

The current implementation uses shared parameter names like q, s, and f.columnId, so multiple live URL-synced tables on the same page will collide.

If a page needs multiple tables, keep continuous URL sync on just one of them or avoid the feature entirely until namespacing exists.

Verify production behavior

Before shipping URL sync, verify that:

  • opening a bookmarked or pasted URL restores the expected query state
  • browser back and forward navigation match the chosen historyMode
  • URL state overrides persisted state on first load
  • the page still behaves correctly when the URL contains no datatable params
  • overly large states fail safely and have a saved-view fallback in product guidance

Keep the mental model simple for users

The easiest product framing is:

  • Persistence remembers my setup
  • Saved views give names to reusable setups
  • Copy links share a snapshot on demand
  • URL sync makes the address bar part of the live table experience

If the page does not need that last promise, do not force it.

On this page