Capítulo 7 de 54

Chapter 7: Using useLegacyTable for Incremental Migration

Core Idea

useLegacyTable (from @tanstack/react-table/legacy) is a deprecated compatibility shim that accepts the v8-style API (getCoreRowModel, state/on[X]Change, legacyCreateColumnHelper) while running on v9 internals — a temporary bridge for large codebases that can't migrate every table at once.

Key Concepts

  • Import split: core utilities (flexRender, shared state types like SortingState) still come from @tanstack/react-table; legacy-specific APIs (useLegacyTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel, legacyCreateColumnHelper, LegacyColumnDef) come from the separate @tanstack/react-table/legacy entrypoint.
  • Accepts the exact v8 shape: pass getCoreRowModel(), getSortedRowModel(), etc. directly as options, and manage state/onSortingChange/onColumnFiltersChange/onPaginationChange yourself with useState, exactly like Table v8.
  • legacyCreateColumnHelper<T>() mirrors v8's createColumnHelper (.accessor(...), .display(...)), producing LegacyColumnDef<T>[].
  • Bundle cost: useLegacyTable includes all features by default (no tree-shaking), so it is strictly larger than an equivalent v9 useTable table — this is the price of the compatibility layer, not a bug.
  • Intended use: upgrading dependencies on an existing v8 codebase, migrating one table at a time, or buying time when a full v9 rewrite isn't immediately practical. Not intended as a long-term API.

Code Examples

import { useState } from 'react'
import { flexRender } from '@tanstack/react-table'
import {
  useLegacyTable,
  getCoreRowModel,
  getSortedRowModel,
  legacyCreateColumnHelper,
} from '@tanstack/react-table/legacy'
import type { SortingState } from '@tanstack/react-table'

const columnHelper = legacyCreateColumnHelper<Person>()
const columns = [
  columnHelper.accessor('name', { header: 'Name' }),
  columnHelper.accessor('age', { header: 'Age' }),
]

function LegacyPersonTable({ data }: { data: Person[] }) {
  const [sorting, setSorting] = useState<SortingState>([])
  const table = useLegacyTable({
    columns,
    data,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    state: { sorting },
    onSortingChange: setSorting,
  })
  // render exactly like a v8 table: flexRender(header.column.columnDef.header, header.getContext())
}
  • What it demonstrates: the v8 shape (row-model getters as options, manually-owned state) still compiles and runs against v9.

Key Takeaways

  1. Reach for useLegacyTable only as a bridge, table by table, never as the new default — it's deprecated on arrival and ships every feature (no tree-shaking).
  2. Legacy imports come from @tanstack/react-table/legacy, a different entrypoint than the rest of v9 — mixing them up is the most common setup mistake.
  3. Plan the actual migration: swap useLegacyTableuseTable, getCoreRowModel()-as-option → tableFeatures({ ... }), and legacyCreateColumnHelper → the current createColumnHelper, one table at a time.

Connects To

  • Migrating to TanStack Table V9 (React): the full list of breaking changes this shim lets you defer.
  • Legacy API (v8 Compatibility): complete reference for every export under @tanstack/react-table/legacy.
  • Quick Start (React): the target v9 shape to migrate each table toward.