bc-grid
GitHub

State persistence

View source

useBcGridState wires every controlled-state dimension a typical ERP grid consumer would otherwise hand-roll — sort, filter, search, selection, range, expansion, grouping, columnState, page, pageSize, sidebar — and round-trips them through localStorage with one prop.

Tweak sort / filter / group / pin — settings persist to localStorage. Reload the page (Cmd+R) and they come back.
Order #
Customer
Sales rep
Status
Region
Amount
R-000026
Customer 00026
Ben Singh
pending
East
$785.40
R-000027
Customer 00027
Cara Diaz
closed
East
$816.81
R-000028
Customer 00028
Drew Lin
active
East
$848.23
R-000029
Customer 00029
Elena Park
pending
West
$879.65
R-000030
Customer 00030
Felix Roy
closed
West
$911.06
R-000031
Customer 00031
Gita Bose
active
West
$942.48
R-000032
Customer 00032
Henry Kao
pending
West
$973.89
R-000033
Customer 00033
Avery Chen
closed
North
$1,005.31
R-000034
Customer 00034
Ben Singh
active
North
$1,036.72
R-000035
Customer 00035
Cara Diaz
pending
North
$1,068.14
R-000036
Customer 00036
Drew Lin
closed
North
$1,099.56
R-000037
Customer 00037
Elena Park
active
South
$1,130.97
R-000038
Customer 00038
Felix Roy
pending
South
$1,162.39
R-000039
Customer 00039
Gita Bose
closed
South
$1,193.80
R-000040
Customer 00040
Henry Kao
active
South
$1,225.22

Try this

The grid persists every interaction to localStorage immediately. Reload the page; the layout comes back.

  • Sort by Customer; press Cmd+R — sort persists.
  • Apply a Status filter; reload — filter persists.
  • Group by Region, drag-resize a column, hide one — all persist.
  • Click Clear + reload to wipe and start fresh.
  • Different gridId values write to different storage keys — two grids on the same page have independent state.

What useBcGridState owns

  • ~13 controlled-state dimensions. sort, filter, search, selection, rangeSelection, expansion, groupBy, pivotState, columnState, activeCell, page, pageSize, sidebarPanel.
  • A single bound props object. <BcGrid {...grid.props} columns={...} data={...} rowId={...} />. That replaces the ~30 lines of useState + onChange wiring most consumers had.
  • Imperative dispatch. grid.dispatch.setSort(...) for cases where the host needs to drive a dimension externally — saved-view picker, URL hydration, "Clear filters" button outside the grid.
  • Defaults. useBcGridState({ defaults: { pageSize: 50 } }). Applied when the user has no persisted value for that dimension yet.

The persistTo target

  • local:<gridId> — the only built-in target today. Writes go to window.localStorage under keys prefixed by the gridId so multiple grids round-trip independently.
  • SSR safe. The hook falls through to the default-empty values when storage is unavailable (SSR, sandboxed iframes, quota errors, private browsing) — never throws.
  • Best-effort writes. Storage failures are silently swallowed. If localStorage is full or blocked, the grid still works; it just doesn't persist.
  • Other targets. Server-side persistence and URL persistence are consumer-side wiring (today). For URL, see the next page; for server, the saved-view DTO is the right primitive.