@tanstack/react-table 9.0.0-alpha.9 → 9.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +127 -0
  2. package/dist/FlexRender.cjs +61 -0
  3. package/dist/FlexRender.cjs.map +1 -0
  4. package/dist/FlexRender.d.cts +51 -0
  5. package/dist/FlexRender.d.ts +51 -0
  6. package/dist/FlexRender.js +58 -0
  7. package/dist/FlexRender.js.map +1 -0
  8. package/dist/Subscribe.cjs +13 -0
  9. package/dist/Subscribe.cjs.map +1 -0
  10. package/dist/Subscribe.d.cts +101 -0
  11. package/dist/Subscribe.d.ts +101 -0
  12. package/dist/Subscribe.js +13 -0
  13. package/dist/Subscribe.js.map +1 -0
  14. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  15. package/dist/createTableHook.cjs +313 -0
  16. package/dist/createTableHook.cjs.map +1 -0
  17. package/dist/createTableHook.d.cts +358 -0
  18. package/dist/createTableHook.d.ts +358 -0
  19. package/dist/createTableHook.js +311 -0
  20. package/dist/createTableHook.js.map +1 -0
  21. package/dist/flex-render.cjs +5 -0
  22. package/dist/flex-render.d.cts +2 -0
  23. package/dist/flex-render.d.ts +2 -0
  24. package/dist/flex-render.js +3 -0
  25. package/dist/index.cjs +18 -0
  26. package/dist/index.d.cts +6 -0
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.js +8 -0
  29. package/dist/legacy.cjs +14 -0
  30. package/dist/legacy.d.cts +2 -0
  31. package/dist/legacy.d.ts +2 -0
  32. package/dist/legacy.js +3 -0
  33. package/dist/reactivity.cjs +34 -0
  34. package/dist/reactivity.cjs.map +1 -0
  35. package/dist/reactivity.js +34 -0
  36. package/dist/reactivity.js.map +1 -0
  37. package/dist/static-functions.cjs +9 -0
  38. package/dist/static-functions.d.cts +1 -0
  39. package/dist/static-functions.d.ts +1 -0
  40. package/dist/static-functions.js +3 -0
  41. package/dist/useLegacyTable.cjs +191 -0
  42. package/dist/useLegacyTable.cjs.map +1 -0
  43. package/dist/useLegacyTable.d.cts +233 -0
  44. package/dist/useLegacyTable.d.ts +233 -0
  45. package/dist/useLegacyTable.js +181 -0
  46. package/dist/useLegacyTable.js.map +1 -0
  47. package/dist/useTable.cjs +72 -0
  48. package/dist/useTable.cjs.map +1 -0
  49. package/dist/useTable.d.cts +122 -0
  50. package/dist/useTable.d.ts +122 -0
  51. package/dist/useTable.js +72 -0
  52. package/dist/useTable.js.map +1 -0
  53. package/package.json +41 -22
  54. package/skills/react/client-to-server/SKILL.md +377 -0
  55. package/skills/react/compose-with-tanstack-form/SKILL.md +363 -0
  56. package/skills/react/compose-with-tanstack-pacer/SKILL.md +287 -0
  57. package/skills/react/compose-with-tanstack-query/SKILL.md +467 -0
  58. package/skills/react/compose-with-tanstack-store/SKILL.md +347 -0
  59. package/skills/react/compose-with-tanstack-virtual/SKILL.md +388 -0
  60. package/skills/react/compose-with-tanstack-virtual/references/column-virtualization-and-infinite-scroll.md +136 -0
  61. package/skills/react/getting-started/SKILL.md +388 -0
  62. package/skills/react/migrate-v8-to-v9/SKILL.md +488 -0
  63. package/skills/react/production-readiness/SKILL.md +341 -0
  64. package/skills/react/react-subscribe-compiler-compat/SKILL.md +269 -0
  65. package/skills/react/table-state/SKILL.md +432 -0
  66. package/src/FlexRender.tsx +136 -0
  67. package/src/Subscribe.ts +153 -0
  68. package/src/createTableHook.tsx +1121 -0
  69. package/src/flex-render.ts +1 -0
  70. package/src/index.ts +6 -0
  71. package/src/legacy.ts +3 -0
  72. package/src/reactivity.ts +41 -0
  73. package/src/static-functions.ts +1 -0
  74. package/src/useLegacyTable.ts +487 -0
  75. package/src/useTable.ts +191 -0
  76. package/dist/cjs/index.cjs +0 -77
  77. package/dist/cjs/index.cjs.map +0 -1
  78. package/dist/cjs/index.d.cts +0 -9
  79. package/dist/esm/index.d.ts +0 -9
  80. package/dist/esm/index.js +0 -55
  81. package/dist/esm/index.js.map +0 -1
  82. package/src/index.tsx +0 -92
@@ -0,0 +1,347 @@
1
+ ---
2
+ name: react/compose-with-tanstack-store
3
+ description: >
4
+ `@tanstack/react-table` v9 is built on TanStack Store. Each state slice
5
+ (sorting, pagination, rowSelection, columnFilters, …) is a separate atom.
6
+ The table exposes three READ surfaces — `table.atoms.<slice>` (per-slice
7
+ readonly), `table.store` (flat readonly view), `table.state` (selector
8
+ output from `useTable`) — and two WRITE paths — internal
9
+ `table.baseAtoms.<slice>` OR YOUR `options.atoms[slice]` if you opt to own
10
+ the slice. Use `useCreateAtom` from `@tanstack/react-store` for stable
11
+ identity, `useSelector` for fine-grained reads, and pass the atom in
12
+ `options.atoms` so the table writes through it directly — no `on*Change`
13
+ handler required.
14
+ type: composition
15
+ library: tanstack-table
16
+ framework: react
17
+ library_version: '9.0.0-alpha.48'
18
+ requires:
19
+ - react/table-state
20
+ - state-management
21
+ sources:
22
+ - TanStack/table:docs/framework/react/guide/table-state.md
23
+ - TanStack/table:examples/react/basic-external-atoms/src/main.tsx
24
+ - TanStack/table:examples/react/basic-subscribe/src/main.tsx
25
+ ---
26
+
27
+ This skill builds on `tanstack-table/state-management` and `tanstack-table/react/table-state`. Read those first — `state-management` explains the atom model conceptually; `table-state` covers the basic React adapter. This skill goes deeper into composition with `@tanstack/react-store`.
28
+
29
+ ## What "compose with TanStack Store" means in practice
30
+
31
+ A v9 React table is already a Store consumer — every slice (`sorting`, `pagination`, `rowSelection`, `columnFilters`, `columnVisibility`, …) is an atom managed by Store. Composing with Store means **opting to own one or more of those atoms yourself** so you can:
32
+
33
+ - Share a slice across multiple components without prop-drilling the table instance.
34
+ - Share a slice across multiple **tables** (e.g. a global filter atom).
35
+ - Persist a slice (subscribe to localStorage outside the table).
36
+ - Integrate with other atom-based code (atoms in your data layer).
37
+ - Skip the `on*Change` callback dance — the table writes through your atom directly.
38
+
39
+ ## Setup
40
+
41
+ Install `@tanstack/react-store` if you don't already have it (it's a peer of `@tanstack/react-table`):
42
+
43
+ ```bash
44
+ pnpm add @tanstack/react-store
45
+ ```
46
+
47
+ Three APIs do the work:
48
+
49
+ ```tsx
50
+ import { useCreateAtom, useSelector } from '@tanstack/react-store'
51
+ ```
52
+
53
+ - `useCreateAtom<T>(initial)` — create an atom with stable identity inside a component (React-safe replacement for `useRef(createAtom(...))`).
54
+ - `useSelector(atomOrStore, selector?)` — subscribe a component to an atom or store.
55
+ - The table's `options.atoms` option — hand ownership of named slices to your atoms.
56
+
57
+ ## Core Patterns
58
+
59
+ ### 1. Own a slice externally
60
+
61
+ ```tsx
62
+ import { useCreateAtom, useSelector } from '@tanstack/react-store'
63
+ import {
64
+ useTable,
65
+ tableFeatures,
66
+ rowSortingFeature,
67
+ rowPaginationFeature,
68
+ createSortedRowModel,
69
+ createPaginatedRowModel,
70
+ sortFns,
71
+ } from '@tanstack/react-table'
72
+ import type { PaginationState, SortingState } from '@tanstack/react-table'
73
+
74
+ const features = tableFeatures({ rowSortingFeature, rowPaginationFeature })
75
+
76
+ function MyTable({ columns, data }) {
77
+ const sortingAtom = useCreateAtom<SortingState>([])
78
+ const paginationAtom = useCreateAtom<PaginationState>({
79
+ pageIndex: 0,
80
+ pageSize: 10,
81
+ })
82
+
83
+ // Fine-grained reads — each component re-renders independently.
84
+ const sorting = useSelector(sortingAtom)
85
+ const pagination = useSelector(paginationAtom)
86
+
87
+ const table = useTable({
88
+ features,
89
+ rowModels: {
90
+ sortedRowModel: createSortedRowModel(sortFns),
91
+ paginatedRowModel: createPaginatedRowModel(),
92
+ },
93
+ columns,
94
+ data,
95
+ atoms: { sorting: sortingAtom, pagination: paginationAtom },
96
+ // NOTE: no onSortingChange / onPaginationChange — table writes to atoms directly.
97
+ })
98
+
99
+ // You own the atom → you own its reset.
100
+ const resetMyState = () => {
101
+ sortingAtom.set([])
102
+ paginationAtom.set({ pageIndex: 0, pageSize: 10 })
103
+ }
104
+ }
105
+ ```
106
+
107
+ Source: `examples/react/basic-external-atoms/src/main.tsx`.
108
+
109
+ ### 2. Read a table-owned atom from a sibling component
110
+
111
+ You don't have to own a slice to read it surgically — `table.atoms.<slice>` works with `useSelector` too.
112
+
113
+ ```tsx
114
+ function SelectedCount({ table }) {
115
+ // Re-renders ONLY when rowSelection changes.
116
+ const selection = useSelector(table.atoms.rowSelection)
117
+ return <span>{Object.keys(selection).length} selected</span>
118
+ }
119
+ ```
120
+
121
+ ### 3. Persist a slice to localStorage
122
+
123
+ Because you own the atom, you can do anything you want outside the table render path:
124
+
125
+ ```tsx
126
+ const visibilityAtom = useCreateAtom<Record<string, boolean>>(() =>
127
+ JSON.parse(localStorage.getItem('cv') ?? '{}'),
128
+ )
129
+
130
+ React.useEffect(() => {
131
+ return visibilityAtom.subscribe(() => {
132
+ localStorage.setItem('cv', JSON.stringify(visibilityAtom.get()))
133
+ })
134
+ }, [visibilityAtom])
135
+
136
+ const table = useTable({
137
+ features,
138
+ rowModels: {},
139
+ columns,
140
+ data,
141
+ atoms: { columnVisibility: visibilityAtom },
142
+ })
143
+ ```
144
+
145
+ ### 4. Share one slice across multiple tables
146
+
147
+ Create the atom outside any component (or in a parent and pass down):
148
+
149
+ ```tsx
150
+ import { createAtom } from '@tanstack/store'
151
+
152
+ const globalFilterAtom = createAtom('')
153
+
154
+ function UsersTable() {
155
+ return <Table data={users} filter={globalFilterAtom} />
156
+ }
157
+ function OrdersTable() {
158
+ return <Table data={orders} filter={globalFilterAtom} />
159
+ }
160
+
161
+ function Table({ data, filter }) {
162
+ const table = useTable({
163
+ features,
164
+ rowModels: {
165
+ /* … */
166
+ },
167
+ columns,
168
+ data,
169
+ atoms: { globalFilter: filter },
170
+ })
171
+ }
172
+ ```
173
+
174
+ ## Read surfaces and write paths — cheat sheet
175
+
176
+ | Surface | Reactive | Use case |
177
+ | ----------------------------------- | --------------------------- | --------------------------------------------------------------- |
178
+ | `table.state` | ✓ (via `useTable` selector) | Default top-level reads in the component that called `useTable` |
179
+ | `<table.Subscribe>` / `<Subscribe>` | ✓ | Surgical re-render boundaries inside the tree |
180
+ | `useSelector(table.atoms.X)` | ✓ | Narrowest possible subscription to one slice |
181
+ | `table.atoms.X.get()` | ✗ current-value read | Inside event handlers / effects |
182
+ | `table.state` | ✗ current-value read | Debugging / one-shot reads |
183
+
184
+ | Write path | Owner | Effect |
185
+ | ------------------------------- | ----------------- | ---------------------------------------------------------------------------------- |
186
+ | Internal `table.baseAtoms.X` | The table | Used when you provide neither `options.atoms.X` nor `options.state.X` |
187
+ | `options.atoms.X` (yours) | You | Table writes through; you can `.set()` from anywhere |
188
+ | `options.state.X` + `onXChange` | You (React state) | Classic controlled state. Cannot coexist with `options.atoms.X` for the same slice |
189
+
190
+ Precedence: `options.atoms[key]` > `options.state[key]` > internal.
191
+
192
+ ## Common Mistakes
193
+
194
+ ### CRITICAL Creating the atom with `createAtom(...)` inside the component body
195
+
196
+ Wrong:
197
+
198
+ ```tsx
199
+ function MyTable() {
200
+ const sortingAtom = createAtom<SortingState>([]) // new atom every render
201
+ useTable({
202
+ features,
203
+ rowModels: {},
204
+ columns,
205
+ data,
206
+ atoms: { sorting: sortingAtom },
207
+ })
208
+ }
209
+ ```
210
+
211
+ Correct:
212
+
213
+ ```tsx
214
+ function MyTable() {
215
+ const sortingAtom = useCreateAtom<SortingState>([]) // stable across renders
216
+ useTable({
217
+ features,
218
+ rowModels: {},
219
+ columns,
220
+ data,
221
+ atoms: { sorting: sortingAtom },
222
+ })
223
+ }
224
+ ```
225
+
226
+ A fresh atom every render rebinds the table to a new atom whose state is the initial value — the slice resets on every render.
227
+ Source: `examples/react/basic-external-atoms/src/main.tsx`.
228
+
229
+ ### HIGH Passing the same slice via `state` AND `atoms`
230
+
231
+ Wrong:
232
+
233
+ ```tsx
234
+ useTable({
235
+ features,
236
+ rowModels: {},
237
+ columns,
238
+ data,
239
+ state: { sorting: localSorting }, // silently ignored
240
+ onSortingChange: setLocalSorting, // silently ignored
241
+ atoms: { sorting: sortingAtom }, // wins
242
+ })
243
+ ```
244
+
245
+ Correct:
246
+
247
+ ```tsx
248
+ // Pick exactly one ownership mechanism per slice.
249
+ useTable({
250
+ features,
251
+ rowModels: {},
252
+ columns,
253
+ data,
254
+ atoms: { sorting: sortingAtom },
255
+ })
256
+ ```
257
+
258
+ `options.atoms[key]` > `options.state[key]`. Confusing to debug because the `state` plumbing looks live but does nothing.
259
+ Source: `docs/framework/react/guide/table-state.md`.
260
+
261
+ ### HIGH Pairing external atoms with `on*Change` handlers
262
+
263
+ Wrong:
264
+
265
+ ```tsx
266
+ useTable({
267
+ features,
268
+ rowModels: {},
269
+ columns,
270
+ data,
271
+ atoms: { sorting: sortingAtom },
272
+ onSortingChange: (next) => sortingAtom.set(next), // redundant + confusing
273
+ })
274
+ ```
275
+
276
+ Correct:
277
+
278
+ ```tsx
279
+ useTable({
280
+ features,
281
+ rowModels: {},
282
+ columns,
283
+ data,
284
+ atoms: { sorting: sortingAtom },
285
+ })
286
+ ```
287
+
288
+ The table writes directly to the atom you provided via the atom's `set()`. Adding an `on*Change` does nothing useful and confuses readers.
289
+ Source: `examples/react/basic-external-atoms/src/main.tsx`.
290
+
291
+ ### HIGH Expecting `table.reset()` to clear externally-owned atoms
292
+
293
+ Wrong:
294
+
295
+ ```tsx
296
+ <button onClick={() => table.reset()}>Reset</button>
297
+ // External atoms remain at their current values — table can't reset what it doesn't own.
298
+ ```
299
+
300
+ Correct:
301
+
302
+ ```tsx
303
+ <button
304
+ onClick={() => {
305
+ sortingAtom.set([])
306
+ paginationAtom.set({ pageIndex: 0, pageSize: 10 })
307
+ table.reset() // resets the slices the table still owns
308
+ }}
309
+ >
310
+ Reset
311
+ </button>
312
+ ```
313
+
314
+ The table only resets slices it manages internally. Your atoms are yours to reset.
315
+ Source: `docs/framework/react/guide/table-state.md`.
316
+
317
+ ### MEDIUM Reading via `table.state.sorting` in deeply-nested components
318
+
319
+ Wrong:
320
+
321
+ ```tsx
322
+ function SortIndicator({ table }) {
323
+ const { sorting } = table.state // re-renders when ANY state slice changes
324
+ return <span>{sorting.length} cols</span>
325
+ }
326
+ ```
327
+
328
+ Correct:
329
+
330
+ ```tsx
331
+ import { useSelector } from '@tanstack/react-store'
332
+
333
+ function SortIndicator({ table }) {
334
+ const sorting = useSelector(table.atoms.sorting) // re-renders only on sorting changes
335
+ return <span>{sorting.length} cols</span>
336
+ }
337
+ ```
338
+
339
+ `useSelector(table.atoms.X)` is the narrowest subscription surface — skips constructing a state snapshot.
340
+ Source: `docs/framework/react/guide/table-state.md`.
341
+
342
+ ## See Also
343
+
344
+ - `tanstack-table/react/table-state` — the base API, includes `<Subscribe>` and `<table.Subscribe>` shapes.
345
+ - `tanstack-table/react/compose-with-tanstack-query` — Query queryKey keyed on a Store atom is the canonical pattern.
346
+ - `tanstack-table/react/production-readiness` — narrowing selectors and per-slice subscriptions.
347
+ - `tanstack-table/react/client-to-server` — atoms make manual-mode wiring trivial.