@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.
- package/README.md +127 -0
- package/dist/FlexRender.cjs +61 -0
- package/dist/FlexRender.cjs.map +1 -0
- package/dist/FlexRender.d.cts +51 -0
- package/dist/FlexRender.d.ts +51 -0
- package/dist/FlexRender.js +58 -0
- package/dist/FlexRender.js.map +1 -0
- package/dist/Subscribe.cjs +13 -0
- package/dist/Subscribe.cjs.map +1 -0
- package/dist/Subscribe.d.cts +101 -0
- package/dist/Subscribe.d.ts +101 -0
- package/dist/Subscribe.js +13 -0
- package/dist/Subscribe.js.map +1 -0
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/createTableHook.cjs +313 -0
- package/dist/createTableHook.cjs.map +1 -0
- package/dist/createTableHook.d.cts +358 -0
- package/dist/createTableHook.d.ts +358 -0
- package/dist/createTableHook.js +311 -0
- package/dist/createTableHook.js.map +1 -0
- package/dist/flex-render.cjs +5 -0
- package/dist/flex-render.d.cts +2 -0
- package/dist/flex-render.d.ts +2 -0
- package/dist/flex-render.js +3 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/legacy.cjs +14 -0
- package/dist/legacy.d.cts +2 -0
- package/dist/legacy.d.ts +2 -0
- package/dist/legacy.js +3 -0
- package/dist/reactivity.cjs +34 -0
- package/dist/reactivity.cjs.map +1 -0
- package/dist/reactivity.js +34 -0
- package/dist/reactivity.js.map +1 -0
- package/dist/static-functions.cjs +9 -0
- package/dist/static-functions.d.cts +1 -0
- package/dist/static-functions.d.ts +1 -0
- package/dist/static-functions.js +3 -0
- package/dist/useLegacyTable.cjs +191 -0
- package/dist/useLegacyTable.cjs.map +1 -0
- package/dist/useLegacyTable.d.cts +233 -0
- package/dist/useLegacyTable.d.ts +233 -0
- package/dist/useLegacyTable.js +181 -0
- package/dist/useLegacyTable.js.map +1 -0
- package/dist/useTable.cjs +72 -0
- package/dist/useTable.cjs.map +1 -0
- package/dist/useTable.d.cts +122 -0
- package/dist/useTable.d.ts +122 -0
- package/dist/useTable.js +72 -0
- package/dist/useTable.js.map +1 -0
- package/package.json +41 -22
- package/skills/react/client-to-server/SKILL.md +377 -0
- package/skills/react/compose-with-tanstack-form/SKILL.md +363 -0
- package/skills/react/compose-with-tanstack-pacer/SKILL.md +287 -0
- package/skills/react/compose-with-tanstack-query/SKILL.md +467 -0
- package/skills/react/compose-with-tanstack-store/SKILL.md +347 -0
- package/skills/react/compose-with-tanstack-virtual/SKILL.md +388 -0
- package/skills/react/compose-with-tanstack-virtual/references/column-virtualization-and-infinite-scroll.md +136 -0
- package/skills/react/getting-started/SKILL.md +388 -0
- package/skills/react/migrate-v8-to-v9/SKILL.md +488 -0
- package/skills/react/production-readiness/SKILL.md +341 -0
- package/skills/react/react-subscribe-compiler-compat/SKILL.md +269 -0
- package/skills/react/table-state/SKILL.md +432 -0
- package/src/FlexRender.tsx +136 -0
- package/src/Subscribe.ts +153 -0
- package/src/createTableHook.tsx +1121 -0
- package/src/flex-render.ts +1 -0
- package/src/index.ts +6 -0
- package/src/legacy.ts +3 -0
- package/src/reactivity.ts +41 -0
- package/src/static-functions.ts +1 -0
- package/src/useLegacyTable.ts +487 -0
- package/src/useTable.ts +191 -0
- package/dist/cjs/index.cjs +0 -77
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.d.cts +0 -9
- package/dist/esm/index.d.ts +0 -9
- package/dist/esm/index.js +0 -55
- package/dist/esm/index.js.map +0 -1
- package/src/index.tsx +0 -92
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react/getting-started
|
|
3
|
+
description: >
|
|
4
|
+
End-to-end first-table journey for `@tanstack/react-table` v9. Install the
|
|
5
|
+
React adapter, declare `features` via `tableFeatures()`, declare `rowModels`
|
|
6
|
+
factories with their *Fns parameters (`createSortedRowModel(sortFns)` etc.),
|
|
7
|
+
create a column helper with both `TFeatures` and `TData` generics, instantiate
|
|
8
|
+
`useTable`, and render with `<table.FlexRender>`. New users land here, not on
|
|
9
|
+
`useLegacyTable`.
|
|
10
|
+
type: lifecycle
|
|
11
|
+
library: tanstack-table
|
|
12
|
+
framework: react
|
|
13
|
+
library_version: '9.0.0-alpha.48'
|
|
14
|
+
requires:
|
|
15
|
+
- setup
|
|
16
|
+
- column-definitions
|
|
17
|
+
- state-management
|
|
18
|
+
- react/table-state
|
|
19
|
+
sources:
|
|
20
|
+
- TanStack/table:docs/installation.md
|
|
21
|
+
- TanStack/table:docs/framework/react/react-table.md
|
|
22
|
+
- TanStack/table:examples/react/basic-use-table/src/main.tsx
|
|
23
|
+
- TanStack/table:examples/react/basic-use-app-table/src/main.tsx
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
This skill builds on `tanstack-table/state-management` and `tanstack-table/react/table-state`. Read those first — `features` + `rowModels` come from the core state-management concept, and `table-state` covers how reactivity flows in React.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add @tanstack/react-table
|
|
32
|
+
# or
|
|
33
|
+
npm install @tanstack/react-table
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`@tanstack/react-table` v9 requires React 18+ and TypeScript 5.4+ if you use TS.
|
|
37
|
+
|
|
38
|
+
## Minimum-viable v9 table
|
|
39
|
+
|
|
40
|
+
Three things are non-negotiable, even for the simplest possible table:
|
|
41
|
+
|
|
42
|
+
1. `features: tableFeatures({...})` — required even if empty (`tableFeatures({})`).
|
|
43
|
+
2. `rowModels: {...}` — required even if empty (`rowModels: {}`). The **core** row model is automatic; you only register sorted/filtered/paginated/grouped/etc. when you use them.
|
|
44
|
+
3. `createColumnHelper<typeof features, TData>()` — generic order is `<TFeatures, TData>` in v9 (changed from v8).
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import * as React from 'react'
|
|
48
|
+
import { useTable, tableFeatures } from '@tanstack/react-table'
|
|
49
|
+
import type { ColumnDef } from '@tanstack/react-table'
|
|
50
|
+
|
|
51
|
+
type Person = {
|
|
52
|
+
firstName: string
|
|
53
|
+
lastName: string
|
|
54
|
+
age: number
|
|
55
|
+
visits: number
|
|
56
|
+
status: string
|
|
57
|
+
progress: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 1. features — required option, even if empty.
|
|
61
|
+
const features = tableFeatures({})
|
|
62
|
+
|
|
63
|
+
// 2. Columns — defined at module scope for stable identity.
|
|
64
|
+
const columns: Array<ColumnDef<typeof features, Person>> = [
|
|
65
|
+
{
|
|
66
|
+
accessorKey: 'firstName',
|
|
67
|
+
header: 'First Name',
|
|
68
|
+
cell: (info) => info.getValue(),
|
|
69
|
+
},
|
|
70
|
+
{ accessorKey: 'lastName', header: 'Last Name' },
|
|
71
|
+
{ accessorKey: 'age', header: 'Age' },
|
|
72
|
+
{ accessorKey: 'visits', header: 'Visits' },
|
|
73
|
+
{ accessorKey: 'status', header: 'Status' },
|
|
74
|
+
{ accessorKey: 'progress', header: 'Profile Progress' },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
function App({ initialData }: { initialData: Person[] }) {
|
|
78
|
+
const [data] = React.useState(() => initialData)
|
|
79
|
+
|
|
80
|
+
// 3. Build the table — `rowModels: {}` is required.
|
|
81
|
+
const table = useTable(
|
|
82
|
+
{
|
|
83
|
+
features,
|
|
84
|
+
rowModels: {},
|
|
85
|
+
columns,
|
|
86
|
+
data,
|
|
87
|
+
},
|
|
88
|
+
(state) => state, // default selector
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<table>
|
|
93
|
+
<thead>
|
|
94
|
+
{table.getHeaderGroups().map((hg) => (
|
|
95
|
+
<tr key={hg.id}>
|
|
96
|
+
{hg.headers.map((h) => (
|
|
97
|
+
<th key={h.id}>
|
|
98
|
+
{h.isPlaceholder ? null : <table.FlexRender header={h} />}
|
|
99
|
+
</th>
|
|
100
|
+
))}
|
|
101
|
+
</tr>
|
|
102
|
+
))}
|
|
103
|
+
</thead>
|
|
104
|
+
<tbody>
|
|
105
|
+
{table.getRowModel().rows.map((row) => (
|
|
106
|
+
<tr key={row.id}>
|
|
107
|
+
{row.getAllCells().map((cell) => (
|
|
108
|
+
<td key={cell.id}>
|
|
109
|
+
<table.FlexRender cell={cell} />
|
|
110
|
+
</td>
|
|
111
|
+
))}
|
|
112
|
+
</tr>
|
|
113
|
+
))}
|
|
114
|
+
</tbody>
|
|
115
|
+
</table>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Source: `examples/react/basic-use-table/src/main.tsx`.
|
|
121
|
+
|
|
122
|
+
## Adding sorting
|
|
123
|
+
|
|
124
|
+
Register the feature in `features`, the factory in `rowModels`, and wire a click handler:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import {
|
|
128
|
+
useTable,
|
|
129
|
+
tableFeatures,
|
|
130
|
+
rowSortingFeature,
|
|
131
|
+
createSortedRowModel,
|
|
132
|
+
sortFns,
|
|
133
|
+
createColumnHelper,
|
|
134
|
+
} from '@tanstack/react-table'
|
|
135
|
+
|
|
136
|
+
const features = tableFeatures({ rowSortingFeature })
|
|
137
|
+
const columnHelper = createColumnHelper<typeof features, Person>()
|
|
138
|
+
|
|
139
|
+
const columns = columnHelper.columns([
|
|
140
|
+
columnHelper.accessor('firstName', { header: 'First' }),
|
|
141
|
+
columnHelper.accessor('age', { header: 'Age' }),
|
|
142
|
+
])
|
|
143
|
+
|
|
144
|
+
function App({ data }: { data: Person[] }) {
|
|
145
|
+
const table = useTable({
|
|
146
|
+
features,
|
|
147
|
+
rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
148
|
+
columns,
|
|
149
|
+
data,
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<table>
|
|
154
|
+
<thead>
|
|
155
|
+
{table.getHeaderGroups().map((hg) => (
|
|
156
|
+
<tr key={hg.id}>
|
|
157
|
+
{hg.headers.map((h) => (
|
|
158
|
+
<th key={h.id} onClick={h.column.getToggleSortingHandler()}>
|
|
159
|
+
<table.FlexRender header={h} />
|
|
160
|
+
{{ asc: ' 🔼', desc: ' 🔽' }[
|
|
161
|
+
h.column.getIsSorted() as string
|
|
162
|
+
] ?? null}
|
|
163
|
+
</th>
|
|
164
|
+
))}
|
|
165
|
+
</tr>
|
|
166
|
+
))}
|
|
167
|
+
</thead>
|
|
168
|
+
{/* tbody same as above */}
|
|
169
|
+
</table>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`createSortedRowModel` REQUIRES `sortFns` (and the equivalents for `createFilteredRowModel(filterFns)`, `createGroupedRowModel(aggregationFns)`). The factory parameter is what makes the registry tree-shakeable.
|
|
175
|
+
|
|
176
|
+
## Layering features
|
|
177
|
+
|
|
178
|
+
Adding pagination and filtering is purely additive — register the feature + factory, and call the built-in APIs:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
const features = tableFeatures({
|
|
182
|
+
rowSortingFeature,
|
|
183
|
+
rowPaginationFeature,
|
|
184
|
+
columnFilteringFeature,
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
const table = useTable({
|
|
188
|
+
features,
|
|
189
|
+
rowModels: {
|
|
190
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
191
|
+
filteredRowModel: createFilteredRowModel(filterFns),
|
|
192
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
193
|
+
},
|
|
194
|
+
columns,
|
|
195
|
+
data,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Built-in APIs you should reach for, NOT reimplement:
|
|
199
|
+
table.setSorting([{ id: 'age', desc: true }])
|
|
200
|
+
table.nextPage()
|
|
201
|
+
table.setColumnFilters([{ id: 'firstName', value: 'tan' }])
|
|
202
|
+
column.toggleSorting()
|
|
203
|
+
row.toggleSelected()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Source: `docs/framework/react/react-table.md`; `examples/react/basic-use-table/src/main.tsx`.
|
|
207
|
+
|
|
208
|
+
## Optional: `createTableHook` for shared config
|
|
209
|
+
|
|
210
|
+
If you ship the same `features` / `rowModels` / cell components across many tables, package them once:
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import { createTableHook } from '@tanstack/react-table'
|
|
214
|
+
|
|
215
|
+
const { useAppTable, createAppColumnHelper } = createTableHook({
|
|
216
|
+
features: {},
|
|
217
|
+
rowModels: {},
|
|
218
|
+
debugTable: true,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const columnHelper = createAppColumnHelper<Person>()
|
|
222
|
+
const columns = columnHelper.columns([
|
|
223
|
+
columnHelper.accessor('firstName', { cell: (info) => info.getValue() }),
|
|
224
|
+
])
|
|
225
|
+
|
|
226
|
+
function App({ data }) {
|
|
227
|
+
const table = useAppTable({ columns, data })
|
|
228
|
+
// ... same FlexRender markup
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Source: `examples/react/basic-use-app-table/src/main.tsx`.
|
|
233
|
+
|
|
234
|
+
## Common Mistakes
|
|
235
|
+
|
|
236
|
+
### CRITICAL Forgetting `features: tableFeatures({})`
|
|
237
|
+
|
|
238
|
+
Wrong:
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
const table = useTable({
|
|
242
|
+
rowModels: {},
|
|
243
|
+
columns,
|
|
244
|
+
data,
|
|
245
|
+
})
|
|
246
|
+
// TS: Property 'features' is missing in type
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Correct:
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
const features = tableFeatures({})
|
|
253
|
+
const table = useTable({ features, rowModels: {}, columns, data })
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The option is required even for a "no features" table — pass `tableFeatures({})` or `stockFeatures` if you want v8-style "everything on".
|
|
257
|
+
Source: `examples/react/basic-use-table/src/main.tsx`.
|
|
258
|
+
|
|
259
|
+
### CRITICAL Reimplementing what built-in APIs already provide
|
|
260
|
+
|
|
261
|
+
Wrong:
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
// Reimplements sorting state manually instead of using the API.
|
|
265
|
+
const [sorting, setSorting] = useState([])
|
|
266
|
+
const sortedData = useMemo(
|
|
267
|
+
() => [...data].sort((a, b) => /* custom */),
|
|
268
|
+
[data, sorting],
|
|
269
|
+
)
|
|
270
|
+
// uses sortedData directly, bypassing the table
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Correct:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
const table = useTable({
|
|
277
|
+
features: tableFeatures({ rowSortingFeature }),
|
|
278
|
+
rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
279
|
+
columns,
|
|
280
|
+
data,
|
|
281
|
+
})
|
|
282
|
+
// Then: table.setSorting(...), column.toggleSorting(), header.getToggleSortingHandler()
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Maintainer flags this as the #1 tell that "an AI wrote this." The built-ins handle reset semantics, multi-sort, internal invariants.
|
|
286
|
+
Source: maintainer interview (Phase 4).
|
|
287
|
+
|
|
288
|
+
### CRITICAL API "missing" because the feature was not registered in `features`
|
|
289
|
+
|
|
290
|
+
Wrong:
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
const features = tableFeatures({}) // empty
|
|
294
|
+
const table = useTable({ features, rowModels: {}, columns, data })
|
|
295
|
+
table.setSorting([{ id: 'age', desc: true }]) // TS error — does not exist on this table type
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Correct:
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
const features = tableFeatures({ rowSortingFeature })
|
|
302
|
+
const table = useTable({
|
|
303
|
+
features,
|
|
304
|
+
rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
305
|
+
columns,
|
|
306
|
+
data,
|
|
307
|
+
})
|
|
308
|
+
table.setSorting([{ id: 'age', desc: true }]) // ✓
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
In v9, `features` is a tree-shakeable registry. If a feature isn't listed, TypeScript hides its APIs and the runtime atom is never created — the feature isn't broken, it's just not on.
|
|
312
|
+
Source: maintainer interview (Phase 4); `docs/framework/react/react-table.md`.
|
|
313
|
+
|
|
314
|
+
### HIGH Wrong generic order on `createColumnHelper`
|
|
315
|
+
|
|
316
|
+
Wrong:
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
const columnHelper = createColumnHelper<Person>() // v8 arity
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Correct:
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
const features = tableFeatures({
|
|
326
|
+
/* … */
|
|
327
|
+
})
|
|
328
|
+
const columnHelper = createColumnHelper<typeof features, Person>() // v9: <TFeatures, TData>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
v9 added `TFeatures` as the first generic across `Column`, `Row`, `ColumnDef`, `ColumnMeta`, etc. Use `typeof features` so the same feature set drives types and runtime.
|
|
332
|
+
Source: `docs/framework/react/react-table.md`.
|
|
333
|
+
|
|
334
|
+
### HIGH Defining `features` / `columns` / `data` inside the render body
|
|
335
|
+
|
|
336
|
+
Wrong:
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
function MyTable({ rows }) {
|
|
340
|
+
const features = tableFeatures({ rowSortingFeature }) // new every render
|
|
341
|
+
const columns = [/* … */] // new every render
|
|
342
|
+
return <Table {/* … */} />
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Correct:
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
// Module scope = stable identity.
|
|
350
|
+
const features = tableFeatures({ rowSortingFeature })
|
|
351
|
+
const columns: ColumnDef<typeof features, Person>[] = [
|
|
352
|
+
/* … */
|
|
353
|
+
]
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Internal memoization keys off identity. A new object every render forces full recomputation and can cause subtle re-render issues.
|
|
357
|
+
Source: `examples/react/basic-use-table/src/main.tsx`; FAQ #1.
|
|
358
|
+
|
|
359
|
+
### HIGH Reaching for `useLegacyTable` for a new project
|
|
360
|
+
|
|
361
|
+
Wrong:
|
|
362
|
+
|
|
363
|
+
```tsx
|
|
364
|
+
import { useLegacyTable, getCoreRowModel } from '@tanstack/react-table/legacy'
|
|
365
|
+
const table = useLegacyTable({
|
|
366
|
+
columns,
|
|
367
|
+
data,
|
|
368
|
+
getCoreRowModel: getCoreRowModel(),
|
|
369
|
+
})
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Correct:
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { useTable, tableFeatures } from '@tanstack/react-table'
|
|
376
|
+
const features = tableFeatures({})
|
|
377
|
+
const table = useTable({ features, rowModels: {}, columns, data })
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
`useLegacyTable` is a migration shim for incrementally upgrading v8 codebases. It bundles every feature, lacks `table.Subscribe`, and is deprecated in v9 / scheduled for removal in v10. New code uses `useTable`.
|
|
381
|
+
Source: `docs/framework/react/guide/use-legacy-table.md`.
|
|
382
|
+
|
|
383
|
+
## See Also
|
|
384
|
+
|
|
385
|
+
- `tanstack-table/react/table-state` — selectors, `<Subscribe>`, external atoms, `createTableHook`.
|
|
386
|
+
- `tanstack-table/react/migrate-v8-to-v9` — for codebases upgrading from `useReactTable`.
|
|
387
|
+
- `tanstack-table/react/production-readiness` — once it works, optimize for shipping.
|
|
388
|
+
- `tanstack-table/react/client-to-server` — when you outgrow client-side row processing.
|