tanstack-vue-table-skilld
Use when writing, migrating, or debugging code that imports @tanstack/vue-table (TanStack Table v9 for Vue). Covers useTable with explicit tableFeatures, reactive ref/computed data, FlexRender rendering, atoms-based state, createTableHook conventions, and the v8-to-v9 breaking changes.
How do I install this agent skill?
npx skills add https://github.com/skilld-dev/vue-ecosystem-skills --skill tanstack-vue-table-skilldIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill is a comprehensive documentation and reference guide for the TanStack Vue Table library. It contains API references, migration instructions, best practices, and indexed historical data from GitHub issues and discussions. No malicious patterns, obfuscation, or dangerous execution triggers were detected.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 1 issue
What does this agent skill do?
@tanstack/vue-table 9.2.4
Headless table adapter for Vue 3. Re-exports all of @tanstack/table-core 9.2.4 plus Vue bindings: useTable, FlexRender, flexRender, createTableHook (dist/index.d.ts:4-5).
Environment limits: vue >=3.2 peer dependency, Node >=20, runtime dep @tanstack/store ^0.11.1 (package.json:34-53).
This Skill targets v9 only. Code using useVueTable, getCoreRowModel(), or onStateChange is v8; migrate it first with Migration v8 to v9.
Quick start
<script setup lang="ts">
import { ref } from 'vue'
import { FlexRender, tableFeatures, useTable } from '@tanstack/vue-table'
type Person = { name: string; age: number }
const features = tableFeatures({})
const columns = [
{ accessorKey: 'name', header: 'Name' },
{ accessorKey: 'age', header: 'Age' },
]
const data = ref<Person[]>([{ name: 'Ada', age: 36 }])
const table = useTable({ features, columns, data })
</script>
<template>
<table>
<thead>
<tr v-for="group in table.getHeaderGroups()" :key="group.id">
<th v-for="header in group.headers" :key="header.id">
<FlexRender v-if="!header.isPlaceholder" :header="header" />
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in table.getRowModel().rows" :key="row.id">
<td v-for="cell in row.getAllCells()" :key="cell.id">
<FlexRender :cell="cell" />
</td>
</tr>
</tbody>
</table>
</template>
Source: skills/getting-started/SKILL.md (shipped in the package).
Add features explicitly
Every feature beyond core must be registered, and each row-model slot follows its prerequisite feature in the same tableFeatures call. The core row model is automatic; there is no getCoreRowModel() option.
import {
createSortedRowModel,
rowSortingFeature,
sortFn_alphanumeric,
tableFeatures,
} from '@tanstack/vue-table'
const features = tableFeatures({
rowSortingFeature,
sortedRowModel: createSortedRowModel(),
sortFns: { alphanumeric: sortFn_alphanumeric },
})
APIs are feature-gated: a missing table.atoms.pagination means rowPaginationFeature was not registered. Full feature and slot list: API surface.
State in one place per slice
State is atom-based. Read it inside a tracked boundary (template, computed, watch, or table.Subscribe); a bare read is only a snapshot.
const pageIndex = computed(() => table.atoms.pagination.get().pageIndex)
Controlled slices need a reactive state plus the matching on[State]Change callback that resolves value-or-function updaters:
const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 20 })
const state = computed(() => ({ pagination: pagination.value }))
const onPaginationChange = (next: PaginationState | ((old: PaginationState) => PaginationState)) => {
pagination.value = typeof next === 'function' ? next(pagination.value) : next
}
// pass state and onPaginationChange to useTable
Own each slice exactly once: internal default, initialState, external atoms, or state + callback. Never both atoms.pagination and state.pagination. onStateChange no longer exists; observe table.store instead. Details: API surface.
Rules that prevent most bugs
- Pass
dataas aref/computed, neverdata.value(dist/useTable.d.ts:13-19). Update it by replacing the array (.value = [...]); in-placepush/spliceis not tracked because writable atoms useshallowRef(dist/reactivity.js:50-52). - Keep
featuresandcolumnsstable; do not rebuild arrays per render. - Render through
FlexRendershorthand::cell,:header,:footer. The legacy:render/:propsform still compiles but is the migration target, not the default (dist/FlexRender.d.ts:28-41). - Never destructure or spread row/cell/column/header methods; they are prototype methods using
this. Userow.getValue('name'), notconst read = row.getValue. - In JSX, pass
table.Subscribeits render function as the explicitchildrenprop; Vue JSX children become slots (dist/useTable.d.ts:9-11). - For server-driven tables set the
manual*option (manualPagination: true) and passrowCount. - Optional
stockFeaturesbundles everything; use it only as a temporary audit bridge, not production.
Common mistakes
- HIGH: renaming
useVueTabletouseTablewhile keepinggetSortedRowModeloptions. Move row models and registries intotableFeatures(skills/migrate-v8-to-v9/SKILL.md:156-159). - HIGH:
useTable({ data: data.value })freezes one snapshot; passdata(skills/getting-started/SKILL.md:85-99). - HIGH: reading
table.atoms.sorting.get()outside a tracked boundary; wrap incomputed(skills/table-state/SKILL.md:104-116). - HIGH: assigning the updater function itself (
pagination.value = next) instead of resolving it first (skills/table-state/SKILL.md:146-161). - HIGH:
columnPinning.left/rightno longer exist; v9 usesstart/endlogical pinning (skills/migrate-v8-to-v9/SKILL.md:99-120). - HIGH:
createColumnHelper<Person>()now needs features first:createColumnHelper<typeof features, Person>()(skills/migrate-v8-to-v9/SKILL.md:147-148).
Reusable app conventions
For app-wide table defaults, use createTableHook({ features, tableComponents, cellComponents, headerComponents }) to get useAppTable, createAppColumnHelper, and typed context hooks (dist/createTableHook.d.ts:136-153). Export the context hook with an explicit type to avoid circular inference when registered components import the hook module (skills/create-table-hook/SKILL.md:62-84).
Integrations
- TanStack Query: manual pagination with reactive keys,
rowCount, computed data passthrough. Integrations - TanStack Virtual: virtualize
table.getRowModel().rows, never the source array. Integrations
References
- API surface: exports, subpaths,
useTable/Subscribetypes, features and slots, atoms model. - Migration v8 to v9: full breaking-change map, pinning renames, TypeScript changes, checklist.
- Integrations: TanStack Query and TanStack Virtual composition patterns.
Also in the package
The package ships its own agent skills under skills/ (getting-started, table-state, migrate-v8-to-v9, create-table-hook, with-tanstack-query, with-tanstack-virtual) and mentions npx @tanstack/intent@latest install to wire them into coding agents (README.md:70-78). Verify exact APIs in the installed node_modules/@tanstack/vue-table/dist/index.d.ts; do not reconstruct v9 from v8 memory.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/skilld-dev/vue-ecosystem-skills/tanstack-vue-table-skilld">View tanstack-vue-table-skilld on skillZs</a>