@tanstack/preact-table 9.0.0-alpha.46 → 9.0.0-alpha.48
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 +10 -0
- package/dist/reactivity.cjs +1 -0
- package/dist/reactivity.cjs.map +1 -1
- package/dist/reactivity.js +1 -0
- package/dist/reactivity.js.map +1 -1
- package/package.json +6 -4
- package/skills/preact/client-to-server/SKILL.md +294 -0
- package/skills/preact/compose-with-tanstack-form/SKILL.md +230 -0
- package/skills/preact/compose-with-tanstack-pacer/SKILL.md +186 -0
- package/skills/preact/compose-with-tanstack-query/SKILL.md +283 -0
- package/skills/preact/compose-with-tanstack-store/SKILL.md +263 -0
- package/skills/preact/compose-with-tanstack-virtual/SKILL.md +275 -0
- package/skills/preact/getting-started/SKILL.md +371 -0
- package/skills/preact/migrate-v8-to-v9/SKILL.md +322 -0
- package/skills/preact/production-readiness/SKILL.md +278 -0
- package/skills/preact/table-state/SKILL.md +432 -0
- package/skills/preact/table-state/references/advanced-state-patterns.md +93 -0
- package/src/reactivity.ts +1 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: preact/getting-started
|
|
3
|
+
description: >
|
|
4
|
+
End-to-end first-table journey for `@tanstack/preact-table` v9: install the
|
|
5
|
+
adapter, declare `_features` via `tableFeatures()`, declare `_rowModels` with
|
|
6
|
+
their factories and *Fns parameters, build a typed column helper, call
|
|
7
|
+
`useTable` with stable references, and render with `table.FlexRender`.
|
|
8
|
+
Routing keywords: install preact-table, first table, getting started,
|
|
9
|
+
tableFeatures, _features, _rowModels, useTable, FlexRender, basic-use-table.
|
|
10
|
+
type: lifecycle
|
|
11
|
+
library: tanstack-table
|
|
12
|
+
framework: preact
|
|
13
|
+
library_version: '9.0.0-alpha.47'
|
|
14
|
+
requires:
|
|
15
|
+
- setup
|
|
16
|
+
- column-definitions
|
|
17
|
+
- state-management
|
|
18
|
+
- preact/table-state
|
|
19
|
+
sources:
|
|
20
|
+
- TanStack/table:docs/installation.md
|
|
21
|
+
- TanStack/table:docs/framework/preact/preact-table.md
|
|
22
|
+
- TanStack/table:examples/preact/basic-use-table/src/main.tsx
|
|
23
|
+
- TanStack/table:packages/preact-table/src/useTable.ts
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
This skill walks through a first working Preact v9 table end-to-end. It assumes you have read `tanstack-table/setup` and `tanstack-table/state-management` for core concepts and `tanstack-table/preact/table-state` for adapter wiring.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
`@tanstack/preact-table` is the Preact adapter. It pulls in `@tanstack/table-core` and `@tanstack/preact-store` (used internally for atom-backed state).
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @tanstack/preact-table
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Peer dependency: `preact >=10`.
|
|
37
|
+
|
|
38
|
+
Source: `packages/preact-table/package.json`.
|
|
39
|
+
|
|
40
|
+
## Step 1 — Declare `_features`
|
|
41
|
+
|
|
42
|
+
v9 is explicit about what a table uses. `_features` is a registry of every feature the table needs. Use `tableFeatures({...})` to get an object whose TypeScript shape drives state inference, API surface, and tree-shaking.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import {
|
|
46
|
+
tableFeatures,
|
|
47
|
+
rowPaginationFeature,
|
|
48
|
+
rowSortingFeature,
|
|
49
|
+
} from '@tanstack/preact-table'
|
|
50
|
+
|
|
51
|
+
const _features = tableFeatures({
|
|
52
|
+
rowPaginationFeature,
|
|
53
|
+
rowSortingFeature,
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If `_features` does not include `rowSelectionFeature`, then `table.atoms.rowSelection`, `table.setRowSelection`, `table.getIsAllRowsSelected()`, etc. all become TypeScript errors — and the runtime won't ship that logic. Pass `tableFeatures({})` for a minimum-overhead table with just the core row model.
|
|
58
|
+
|
|
59
|
+
Source: `docs/framework/preact/preact-table.md`; `docs/guide/features.md`.
|
|
60
|
+
|
|
61
|
+
## Step 2 — Declare `_rowModels`
|
|
62
|
+
|
|
63
|
+
Each registered feature that needs a row-model stage maps to a factory under `_rowModels`. The factory takes a record of \*Fns (predicates, comparators, etc.) for that stage.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import {
|
|
67
|
+
createPaginatedRowModel,
|
|
68
|
+
createSortedRowModel,
|
|
69
|
+
sortFns,
|
|
70
|
+
} from '@tanstack/preact-table'
|
|
71
|
+
|
|
72
|
+
const _rowModels = {
|
|
73
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
74
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The core row model is always included — `_rowModels: {}` is valid for a feature-free table.
|
|
79
|
+
|
|
80
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
81
|
+
|
|
82
|
+
## Step 3 — Type your data and build columns
|
|
83
|
+
|
|
84
|
+
Declare your row shape once and feed it to `createColumnHelper<typeof _features, TData>()`. This is the type-safe path; `ColumnDef<typeof _features, Person>[]` also works.
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { createColumnHelper, type ColumnDef } from '@tanstack/preact-table'
|
|
88
|
+
|
|
89
|
+
type Person = {
|
|
90
|
+
firstName: string
|
|
91
|
+
lastName: string
|
|
92
|
+
age: number
|
|
93
|
+
visits: number
|
|
94
|
+
status: string
|
|
95
|
+
progress: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const columnHelper = createColumnHelper<typeof _features, Person>()
|
|
99
|
+
|
|
100
|
+
const columns = columnHelper.columns([
|
|
101
|
+
columnHelper.accessor('firstName', {
|
|
102
|
+
header: 'First Name',
|
|
103
|
+
cell: (info) => info.getValue(),
|
|
104
|
+
}),
|
|
105
|
+
columnHelper.accessor('lastName', { header: () => <span>Last Name</span> }),
|
|
106
|
+
columnHelper.accessor('age', { header: 'Age' }),
|
|
107
|
+
columnHelper.accessor('visits', { header: 'Visits' }),
|
|
108
|
+
columnHelper.accessor('status', { header: 'Status' }),
|
|
109
|
+
columnHelper.accessor('progress', { header: 'Profile Progress' }),
|
|
110
|
+
])
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Source: `examples/preact/basic-use-table/src/main.tsx`.
|
|
114
|
+
|
|
115
|
+
## Step 4 — Call `useTable` and render
|
|
116
|
+
|
|
117
|
+
`useTable` takes options and an optional selector. Render headers, cells, and footers with `table.FlexRender` so column defs can be strings or Preact components.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { render } from 'preact'
|
|
121
|
+
import { useState } from 'preact/hooks'
|
|
122
|
+
import { useTable } from '@tanstack/preact-table'
|
|
123
|
+
|
|
124
|
+
const defaultData: Person[] = [
|
|
125
|
+
{
|
|
126
|
+
firstName: 'tanner',
|
|
127
|
+
lastName: 'linsley',
|
|
128
|
+
age: 24,
|
|
129
|
+
visits: 100,
|
|
130
|
+
status: 'In Relationship',
|
|
131
|
+
progress: 50,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
firstName: 'kevin',
|
|
135
|
+
lastName: 'vandy',
|
|
136
|
+
age: 12,
|
|
137
|
+
visits: 100,
|
|
138
|
+
status: 'Single',
|
|
139
|
+
progress: 70,
|
|
140
|
+
},
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
function App() {
|
|
144
|
+
const [data] = useState(() => [...defaultData])
|
|
145
|
+
|
|
146
|
+
const table = useTable(
|
|
147
|
+
{
|
|
148
|
+
_features,
|
|
149
|
+
_rowModels,
|
|
150
|
+
columns,
|
|
151
|
+
data,
|
|
152
|
+
debugTable: true,
|
|
153
|
+
},
|
|
154
|
+
(state) => state, // default selector
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<table>
|
|
159
|
+
<thead>
|
|
160
|
+
{table.getHeaderGroups().map((hg) => (
|
|
161
|
+
<tr key={hg.id}>
|
|
162
|
+
{hg.headers.map((h) => (
|
|
163
|
+
<th key={h.id} onClick={h.column.getToggleSortingHandler()}>
|
|
164
|
+
{h.isPlaceholder ? null : <table.FlexRender header={h} />}
|
|
165
|
+
</th>
|
|
166
|
+
))}
|
|
167
|
+
</tr>
|
|
168
|
+
))}
|
|
169
|
+
</thead>
|
|
170
|
+
<tbody>
|
|
171
|
+
{table.getRowModel().rows.map((row) => (
|
|
172
|
+
<tr key={row.id}>
|
|
173
|
+
{row.getAllCells().map((cell) => (
|
|
174
|
+
<td key={cell.id}>
|
|
175
|
+
<table.FlexRender cell={cell} />
|
|
176
|
+
</td>
|
|
177
|
+
))}
|
|
178
|
+
</tr>
|
|
179
|
+
))}
|
|
180
|
+
</tbody>
|
|
181
|
+
<tfoot>
|
|
182
|
+
{table.getFooterGroups().map((fg) => (
|
|
183
|
+
<tr key={fg.id}>
|
|
184
|
+
{fg.headers.map((h) => (
|
|
185
|
+
<th key={h.id}>
|
|
186
|
+
{h.isPlaceholder ? null : <table.FlexRender footer={h} />}
|
|
187
|
+
</th>
|
|
188
|
+
))}
|
|
189
|
+
</tr>
|
|
190
|
+
))}
|
|
191
|
+
</tfoot>
|
|
192
|
+
</table>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
render(<App />, document.getElementById('root')!)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Source: `examples/preact/basic-use-table/src/main.tsx`.
|
|
200
|
+
|
|
201
|
+
## Step 5 — Drive features with feature APIs
|
|
202
|
+
|
|
203
|
+
Reach for `table.setSorting(...)`, `table.setPageIndex(...)`, `table.nextPage()`, `column.toggleVisibility()`, `row.toggleSelected()`, etc. — never edit `table.store.state` directly.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<button onClick={() => table.setPageIndex(0)} disabled={!table.getCanPreviousPage()}>First</button>
|
|
207
|
+
<button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>Next</button>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
For starting values, use `initialState`. For controlled slices, use `atoms` (preferred) or `state` + `on*Change` — see `tanstack-table/preact/table-state`.
|
|
211
|
+
|
|
212
|
+
## Common Mistakes
|
|
213
|
+
|
|
214
|
+
### CRITICAL Calling a feature API when the feature is not in `_features`
|
|
215
|
+
|
|
216
|
+
Wrong:
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
const _features = tableFeatures({}) // no rowPaginationFeature
|
|
220
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
221
|
+
|
|
222
|
+
table.setPageIndex(0) // TypeScript error AND runtime no-op
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Correct:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
const _features = tableFeatures({ rowPaginationFeature })
|
|
229
|
+
const table = useTable({
|
|
230
|
+
_features,
|
|
231
|
+
_rowModels: { paginatedRowModel: createPaginatedRowModel() },
|
|
232
|
+
columns,
|
|
233
|
+
data,
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
table.setPageIndex(0)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
v9 generates feature APIs and state slices only for registered features. The missing-feature failure mode (calling `setSorting`, accessing `state.pagination`, etc. before registering the feature) is the #1 v9 trap.
|
|
240
|
+
Source: `docs/guide/features.md`; `docs/framework/preact/guide/table-state.md`.
|
|
241
|
+
|
|
242
|
+
### HIGH Forgetting the matching row-model factory
|
|
243
|
+
|
|
244
|
+
Wrong:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
248
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
249
|
+
table.setSorting([{ id: 'age', desc: true }])
|
|
250
|
+
// table.getRowModel().rows is still unsorted — no sortedRowModel registered
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Correct:
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
257
|
+
const table = useTable({
|
|
258
|
+
_features,
|
|
259
|
+
_rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
260
|
+
columns,
|
|
261
|
+
data,
|
|
262
|
+
})
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Each row-model feature (sorting, filtering, pagination, grouping, expanding, faceting) requires its row-model factory in `_rowModels` to actually transform the rows.
|
|
266
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
267
|
+
|
|
268
|
+
### HIGH Unstable `_features` / `columns` / `data` references
|
|
269
|
+
|
|
270
|
+
Wrong:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
function MyTable({ rows }) {
|
|
274
|
+
const _features = tableFeatures({ rowSortingFeature }) // new every render
|
|
275
|
+
const columns = [
|
|
276
|
+
/* … */
|
|
277
|
+
] // new every render
|
|
278
|
+
const data = rows ?? [] // new [] every render
|
|
279
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Correct:
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
287
|
+
const columns: ColumnDef<typeof _features, Person>[] = [
|
|
288
|
+
/* … */
|
|
289
|
+
]
|
|
290
|
+
const EMPTY: Person[] = []
|
|
291
|
+
|
|
292
|
+
function MyTable({ rows }) {
|
|
293
|
+
const data = rows ?? EMPTY
|
|
294
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Internal memos key off identity. Fresh references bust everything every render.
|
|
299
|
+
Source: `docs/framework/preact/guide/table-state.md` (FAQ #1).
|
|
300
|
+
|
|
301
|
+
### HIGH Reimplementing built-in feature logic
|
|
302
|
+
|
|
303
|
+
Wrong:
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
const sorted = useMemo(() => [...data].sort(/* … */), [data, sorting]) // duplicates rowSortingFeature
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Correct:
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
313
|
+
const table = useTable({
|
|
314
|
+
_features,
|
|
315
|
+
_rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
316
|
+
columns,
|
|
317
|
+
data,
|
|
318
|
+
})
|
|
319
|
+
const rows = table.getRowModel().rows // already sorted
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
v9 ships built-ins for sorting, filtering, pagination, grouping, expanding, faceting, row selection, column visibility/order/pinning/sizing, and row pinning. Use them.
|
|
323
|
+
Source: `docs/guide/features.md`.
|
|
324
|
+
|
|
325
|
+
### MEDIUM Using v8 hook names (`getCoreRowModel`, `useReactTable`, etc.)
|
|
326
|
+
|
|
327
|
+
Wrong:
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
import {
|
|
331
|
+
useReactTable,
|
|
332
|
+
getCoreRowModel,
|
|
333
|
+
getSortedRowModel,
|
|
334
|
+
} from '@tanstack/preact-table'
|
|
335
|
+
const table = useReactTable({
|
|
336
|
+
columns,
|
|
337
|
+
data,
|
|
338
|
+
getCoreRowModel: getCoreRowModel(),
|
|
339
|
+
getSortedRowModel: getSortedRowModel(),
|
|
340
|
+
})
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Correct:
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
import {
|
|
347
|
+
useTable,
|
|
348
|
+
tableFeatures,
|
|
349
|
+
rowSortingFeature,
|
|
350
|
+
createSortedRowModel,
|
|
351
|
+
sortFns,
|
|
352
|
+
} from '@tanstack/preact-table'
|
|
353
|
+
|
|
354
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
355
|
+
|
|
356
|
+
const table = useTable({
|
|
357
|
+
_features,
|
|
358
|
+
_rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
359
|
+
columns,
|
|
360
|
+
data,
|
|
361
|
+
})
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
v8 used `useReactTable` and `get*RowModel` options. v9 uses `useTable` plus `_features` + `_rowModels`. See `tanstack-table/preact/migrate-v8-to-v9` for the full mapping.
|
|
365
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
366
|
+
|
|
367
|
+
## See Also
|
|
368
|
+
|
|
369
|
+
- `tanstack-table/preact/table-state` — atoms, Subscribe, createTableHook.
|
|
370
|
+
- `tanstack-table/preact/migrate-v8-to-v9` — moving an existing v8 codebase over.
|
|
371
|
+
- `tanstack-table/preact/production-readiness` — perf, tree-shaking, stable refs.
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: preact/migrate-v8-to-v9
|
|
3
|
+
description: >
|
|
4
|
+
Mechanical breaking-change migration from TanStack Table v8 to v9 for
|
|
5
|
+
`@tanstack/preact-table`. Maps every old-shaped option, helper, type, and
|
|
6
|
+
method an agent will reproduce from v8 muscle memory to its v9 equivalent:
|
|
7
|
+
`useReactTable` → `useTable`, per-row-model `get*RowModel` options →
|
|
8
|
+
`_features` + `_rowModels`, plain column helpers → typed column helpers,
|
|
9
|
+
`state` + `on*Change` → `atoms`, `flexRender` → `table.FlexRender`, and core
|
|
10
|
+
type renames. Routing keywords: v8 to v9, migration, useReactTable, table
|
|
11
|
+
v8 preact, get*RowModel, _features.
|
|
12
|
+
type: lifecycle
|
|
13
|
+
library: tanstack-table
|
|
14
|
+
framework: preact
|
|
15
|
+
library_version: '9.0.0-alpha.47'
|
|
16
|
+
requires:
|
|
17
|
+
- setup
|
|
18
|
+
- state-management
|
|
19
|
+
- column-definitions
|
|
20
|
+
sources:
|
|
21
|
+
- TanStack/table:docs/framework/preact/preact-table.md
|
|
22
|
+
- TanStack/table:docs/framework/preact/guide/table-state.md
|
|
23
|
+
- TanStack/table:docs/framework/react/guide/use-legacy-table.md
|
|
24
|
+
- TanStack/table:packages/preact-table/src/useTable.ts
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
The Preact adapter mirrors the React v9 surface, so any v8 → v9 migration guide for React applies almost line-for-line. There is no `useLegacyTable` shim in `@tanstack/preact-table` — migrate directly.
|
|
28
|
+
|
|
29
|
+
## The Core Mapping
|
|
30
|
+
|
|
31
|
+
| v8 (Preact / React-compatible) | v9 (`@tanstack/preact-table`) |
|
|
32
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `useReactTable(opts)` | `useTable(opts, selector?)` |
|
|
34
|
+
| `getCoreRowModel: getCoreRowModel()` | included by default — `_rowModels: {}` is valid |
|
|
35
|
+
| `getSortedRowModel: getSortedRowModel()` | `_features: { rowSortingFeature }` + `_rowModels: { sortedRowModel: createSortedRowModel(sortFns) }` |
|
|
36
|
+
| `getFilteredRowModel: getFilteredRowModel()` | `_features: { columnFilteringFeature, globalFilteringFeature }` + `_rowModels: { filteredRowModel: createFilteredRowModel(filterFns) }` |
|
|
37
|
+
| `getPaginationRowModel: getPaginationRowModel()` | `_features: { rowPaginationFeature }` + `_rowModels: { paginatedRowModel: createPaginatedRowModel() }` |
|
|
38
|
+
| `getGroupedRowModel: getGroupedRowModel()` | `_features: { columnGroupingFeature }` + `_rowModels: { groupedRowModel: createGroupedRowModel(aggregationFns) }` |
|
|
39
|
+
| `getExpandedRowModel: getExpandedRowModel()` | `_features: { rowExpandingFeature }` + `_rowModels: { expandedRowModel: createExpandedRowModel() }` |
|
|
40
|
+
| `getFacetedRowModel`, `getFacetedUniqueValues`, `getFacetedMinMaxValues` | `_features: { columnFacetingFeature, globalFacetingFeature }` + `_rowModels: { facetedRowModel: createFacetedRowModel(facetedFns), facetedUniqueValues: createFacetedUniqueValues(), facetedMinMaxValues: createFacetedMinMaxValues() }` |
|
|
41
|
+
| `flexRender(def, ctx)` | `<table.FlexRender cell={cell} />` / `header={...}` / `footer={...}` |
|
|
42
|
+
| `state`, `on*Change` (only) | still supported, plus `atoms` (preferred per slice) |
|
|
43
|
+
| `createColumnHelper<TData>()` | `createColumnHelper<typeof _features, TData>()` — both generics required |
|
|
44
|
+
| `ColumnDef<TData, TValue>` | `ColumnDef<TFeatures, TData, TValue>` — `TFeatures` is now the first generic |
|
|
45
|
+
| `Table<TData>` | `Table<TFeatures, TData>` |
|
|
46
|
+
|
|
47
|
+
Source: `docs/framework/preact/preact-table.md`; `docs/framework/preact/guide/table-state.md`.
|
|
48
|
+
|
|
49
|
+
## Migration Steps
|
|
50
|
+
|
|
51
|
+
### 1. Update the package import
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// v8
|
|
55
|
+
import {
|
|
56
|
+
useReactTable,
|
|
57
|
+
getCoreRowModel,
|
|
58
|
+
getSortedRowModel,
|
|
59
|
+
flexRender,
|
|
60
|
+
type ColumnDef,
|
|
61
|
+
} from '@tanstack/preact-table'
|
|
62
|
+
|
|
63
|
+
// v9
|
|
64
|
+
import {
|
|
65
|
+
useTable,
|
|
66
|
+
tableFeatures,
|
|
67
|
+
rowSortingFeature,
|
|
68
|
+
createSortedRowModel,
|
|
69
|
+
sortFns,
|
|
70
|
+
type ColumnDef,
|
|
71
|
+
} from '@tanstack/preact-table'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. Declare `_features` and `_rowModels`
|
|
75
|
+
|
|
76
|
+
Replace each `get*RowModel: get*RowModel()` option with a feature import + a row-model factory.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// v8
|
|
80
|
+
const table = useReactTable({
|
|
81
|
+
columns,
|
|
82
|
+
data,
|
|
83
|
+
getCoreRowModel: getCoreRowModel(),
|
|
84
|
+
getSortedRowModel: getSortedRowModel(),
|
|
85
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
86
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// v9
|
|
90
|
+
const _features = tableFeatures({
|
|
91
|
+
rowSortingFeature,
|
|
92
|
+
columnFilteringFeature,
|
|
93
|
+
rowPaginationFeature,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const table = useTable({
|
|
97
|
+
_features,
|
|
98
|
+
_rowModels: {
|
|
99
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
100
|
+
filteredRowModel: createFilteredRowModel(filterFns),
|
|
101
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
102
|
+
},
|
|
103
|
+
columns,
|
|
104
|
+
data,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Move `_features` to module scope. Reference stability matters — see `tanstack-table/preact/production-readiness`.
|
|
109
|
+
|
|
110
|
+
### 3. Update column types and helpers
|
|
111
|
+
|
|
112
|
+
`TFeatures` is now the first generic on `ColumnDef`, `Table`, and `createColumnHelper`.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
// v8
|
|
116
|
+
const columnHelper = createColumnHelper<Person>()
|
|
117
|
+
const columns: ColumnDef<Person>[] = columnHelper.columns([
|
|
118
|
+
/* … */
|
|
119
|
+
])
|
|
120
|
+
|
|
121
|
+
// v9
|
|
122
|
+
const columnHelper = createColumnHelper<typeof _features, Person>()
|
|
123
|
+
const columns: Array<ColumnDef<typeof _features, Person>> =
|
|
124
|
+
columnHelper.columns([
|
|
125
|
+
/* … */
|
|
126
|
+
])
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 4. Replace `flexRender` calls with `table.FlexRender`
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
// v8
|
|
133
|
+
<th>{flexRender(header.column.columnDef.header, header.getContext())}</th>
|
|
134
|
+
<td>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
|
|
135
|
+
|
|
136
|
+
// v9
|
|
137
|
+
<th>{header.isPlaceholder ? null : <table.FlexRender header={header} />}</th>
|
|
138
|
+
<td><table.FlexRender cell={cell} /></td>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`flexRender` is still exported for advanced cases, but `table.FlexRender` (or the standalone `FlexRender` component) handles grouping placeholder/aggregated branches for you.
|
|
142
|
+
|
|
143
|
+
Source: `packages/preact-table/src/FlexRender.tsx`.
|
|
144
|
+
|
|
145
|
+
### 5. Move external state to atoms (recommended)
|
|
146
|
+
|
|
147
|
+
`state` + `on*Change` still works, but v9 prefers slice atoms for fine-grained reactivity.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
// v8 / v9 fallback
|
|
151
|
+
const [sorting, setSorting] = useState<SortingState>([])
|
|
152
|
+
const table = useTable({
|
|
153
|
+
_features,
|
|
154
|
+
_rowModels,
|
|
155
|
+
columns,
|
|
156
|
+
data,
|
|
157
|
+
state: { sorting },
|
|
158
|
+
onSortingChange: setSorting,
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// v9 preferred — external atom
|
|
162
|
+
import { useCreateAtom } from '@tanstack/preact-store'
|
|
163
|
+
const sortingAtom = useCreateAtom<SortingState>([])
|
|
164
|
+
const table = useTable({
|
|
165
|
+
_features,
|
|
166
|
+
_rowModels,
|
|
167
|
+
columns,
|
|
168
|
+
data,
|
|
169
|
+
atoms: { sorting: sortingAtom },
|
|
170
|
+
// no onSortingChange needed
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Source: `examples/preact/basic-external-atoms/src/main.tsx`.
|
|
175
|
+
|
|
176
|
+
### 6. Drop `onStateChange`
|
|
177
|
+
|
|
178
|
+
The v8-style global `onStateChange` is gone. Subscribe per-slice with `on*Change`, an external atom, or `table.store.subscribe(...)` if you really need every change.
|
|
179
|
+
|
|
180
|
+
Source: `docs/framework/preact/guide/table-state.md`.
|
|
181
|
+
|
|
182
|
+
## Common Mistakes
|
|
183
|
+
|
|
184
|
+
### CRITICAL Keeping `get*RowModel` options after upgrading
|
|
185
|
+
|
|
186
|
+
Wrong:
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
const table = useTable({
|
|
190
|
+
_features,
|
|
191
|
+
_rowModels: {},
|
|
192
|
+
columns,
|
|
193
|
+
data,
|
|
194
|
+
getSortedRowModel: getSortedRowModel(), // v8 leftover — silently ignored
|
|
195
|
+
})
|
|
196
|
+
table.setSorting([{ id: 'age', desc: true }]) // rows are NOT sorted
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Correct:
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
const _features = tableFeatures({ rowSortingFeature })
|
|
203
|
+
const table = useTable({
|
|
204
|
+
_features,
|
|
205
|
+
_rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
|
|
206
|
+
columns,
|
|
207
|
+
data,
|
|
208
|
+
})
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
v9 doesn't read the `get*RowModel` options. The row model only runs for stages registered in `_rowModels`, and the feature only mounts if it is in `_features`.
|
|
212
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
213
|
+
|
|
214
|
+
### CRITICAL Forgetting to register a feature whose API you are calling
|
|
215
|
+
|
|
216
|
+
Wrong:
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
const _features = tableFeatures({}) // no rowSelectionFeature
|
|
220
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
221
|
+
table.getIsAllRowsSelected() // TypeScript error / runtime no-op
|
|
222
|
+
row.toggleSelected(true) // same
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Correct:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
const _features = tableFeatures({ rowSelectionFeature })
|
|
229
|
+
const table = useTable({
|
|
230
|
+
_features,
|
|
231
|
+
_rowModels: {},
|
|
232
|
+
columns,
|
|
233
|
+
data,
|
|
234
|
+
enableRowSelection: true,
|
|
235
|
+
})
|
|
236
|
+
table.getIsAllRowsSelected()
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
v9 generates feature APIs and state slices only for registered features. This is the #1 v9 trap.
|
|
240
|
+
Source: `docs/guide/features.md`.
|
|
241
|
+
|
|
242
|
+
### HIGH Re-using `getCoreRowModel: getCoreRowModel()` from v8
|
|
243
|
+
|
|
244
|
+
Wrong:
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
const table = useTable({
|
|
248
|
+
_features,
|
|
249
|
+
_rowModels: {},
|
|
250
|
+
columns,
|
|
251
|
+
data,
|
|
252
|
+
getCoreRowModel: getCoreRowModel(), // no-op in v9
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Correct:
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
const table = useTable({ _features, _rowModels: {}, columns, data })
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The core row model is always included in v9. There is no `getCoreRowModel` option.
|
|
263
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
264
|
+
|
|
265
|
+
### HIGH Single-generic column helper / `ColumnDef`
|
|
266
|
+
|
|
267
|
+
Wrong:
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
const columnHelper = createColumnHelper<Person>() // v8 shape
|
|
271
|
+
const columns: ColumnDef<Person>[] = [
|
|
272
|
+
/* … */
|
|
273
|
+
] // v8 shape
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Correct:
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
const columnHelper = createColumnHelper<typeof _features, Person>()
|
|
280
|
+
const columns: Array<ColumnDef<typeof _features, Person>> = [
|
|
281
|
+
/* … */
|
|
282
|
+
]
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`TFeatures` is the first generic for nearly every public type in v9. Without it, types degrade to `any` for feature methods.
|
|
286
|
+
Source: `docs/framework/preact/preact-table.md`.
|
|
287
|
+
|
|
288
|
+
### HIGH Reimplementing built-ins (the #1 AI tell)
|
|
289
|
+
|
|
290
|
+
Wrong:
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
// Manual sorting, manual filtering, manual pagination, manual row-selection objects
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Correct: register the matching feature in `_features`, register its factory in `_rowModels`, and use the feature API. v9 ships built-ins for sorting, filtering, pagination, grouping, expanding, faceting, row selection, column visibility/order/pinning/sizing, and row pinning.
|
|
297
|
+
Source: `docs/guide/features.md`.
|
|
298
|
+
|
|
299
|
+
### MEDIUM Calling `flexRender` directly when grouping is on
|
|
300
|
+
|
|
301
|
+
Wrong:
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
<td>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Correct:
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
<td>
|
|
311
|
+
<table.FlexRender cell={cell} />
|
|
312
|
+
</td>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
`<table.FlexRender cell={...}>` handles aggregated / placeholder cells when `columnGroupingFeature` is registered. Raw `flexRender` does not.
|
|
316
|
+
Source: `packages/preact-table/src/FlexRender.tsx`.
|
|
317
|
+
|
|
318
|
+
## See Also
|
|
319
|
+
|
|
320
|
+
- `tanstack-table/preact/getting-started` — green-field v9 setup.
|
|
321
|
+
- `tanstack-table/preact/table-state` — atom model and Subscribe patterns.
|
|
322
|
+
- `tanstack-table/preact/production-readiness` — perf, tree-shaking, stable refs.
|