File: migrating.md | Updated: 11/15/2025
Search...
+ K
Auto
Docs Examples GitHub Contributors
Docs Examples GitHub Contributors
Docs Examples GitHub Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Maintainers Partners Support Learn StatsBETA Discord Merch Blog GitHub Ethos Brand Guide
Documentation
Framework
React
Version
v8
Search...
+ K
Menu
Getting Started
Core Guides
Feature Guides
Core APIs
Feature APIs
Enterprise
Examples
Framework
React
Version
v8
Menu
Getting Started
Core Guides
Feature Guides
Core APIs
Feature APIs
Enterprise
Examples
On this page
Copy Markdown
Migrating to V8
---------------
TanStack Table V8 was a major rewrite of React Table v7 from the ground up in TypeScript. The overall structure/organization of your markup and CSS will largely remain the same, but many of the APIs have been renamed or replaced.
The new version of TanStack Table is published under the @tanstack scope. Install the new package using your favorite package manager:
bash
npm uninstall react-table @types/react-table
npm install @tanstack/react-table
npm uninstall react-table @types/react-table
npm install @tanstack/react-table
tsx
- import { useTable } from 'react-table'
+ import { useReactTable } from '@tanstack/react-table'
- import { useTable } from 'react-table'
+ import { useReactTable } from '@tanstack/react-table'
Types are now included in the base package, so you can remove the @types/react-table package.
If you want, you can keep the old react-table packages installed so that you can gradually migrate your code. You should be able to use both packages side-by-side for separate tables without any issues.
tsx
- import { useTable, usePagination, useSortBy } from 'react-table';
+ import {
+ useReactTable,
+ getCoreRowModel,
+ getPaginationRowModel,
+ getSortedRowModel
+ } from '@tanstack/react-table';
// ...
- const tableInstance = useTable(
- { columns, data },
- useSortBy,
- usePagination, //order of hooks used to matter
- // etc.
- );
+ const tableInstance = useReactTable({
+ columns,
+ data,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(), //order doesn't matter anymore!
+ // etc.
+ });
- import { useTable, usePagination, useSortBy } from 'react-table';
+ import {
+ useReactTable,
+ getCoreRowModel,
+ getPaginationRowModel,
+ getSortedRowModel
+ } from '@tanstack/react-table';
// ...
- const tableInstance = useTable(
- { columns, data },
- useSortBy,
- usePagination, //order of hooks used to matter
- // etc.
- );
+ const tableInstance = useReactTable({
+ columns,
+ data,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(), //order doesn't matter anymore!
+ // etc.
+ });
tsx
const columns = [\
- { \
- accessor: 'firstName', \
- Header: 'First Name', \
- }, \
- { \
- accessor: row => row.lastName, \
- Header: () => <span>Last Name</span>, \
- }, \
\
// Best TypeScript experience, especially when using `cell.getValue()` later on\
+ columnHelper.accessor('firstName', { //accessorKey\
+ header: 'First Name', \
+ }), \
+ columnHelper.accessor(row => row.lastName, { //accessorFn\
+ header: () => <span>Last Name</span>, \
+ }), \
\
// OR (if you prefer)\
+ { \
+ accessorKey: 'firstName', \
+ header: 'First Name', \
+ }, \
+ { \
+ accessorFn: row => row.lastName, \
+ header: () => <span>Last Name</span>, \
+ }, \
]
const columns = [\
- {\
- accessor: 'firstName',\
- Header: 'First Name',\
- },\
- {\
- accessor: row => row.lastName,\
- Header: () => <span>Last Name</span>,\
- },\
\
// Best TypeScript experience, especially when using `cell.getValue()` later on\
+ columnHelper.accessor('firstName', { //accessorKey\
+ header: 'First Name',\
+ }),\
+ columnHelper.accessor(row => row.lastName, { //accessorFn\
+ header: () => <span>Last Name</span>,\
+ }),\
\
// OR (if you prefer)\
+ {\
+ accessorKey: 'firstName',\
+ header: 'First Name',\
+ },\
+ {\
+ accessorFn: row => row.lastName,\
+ header: () => <span>Last Name</span>,\
+ },\
]
Note: If defining columns inside a component, you should still try to give the column definitions a stable identity. This will help with performance and prevent unnecessary re-renders. Store the column definitions in either a useMemo or useState hook.
Column Option Name Changes
Changes to custom cell renderers
tsx
- <th {...header.getHeaderProps()}>{cell.render('Header')}</th>
+ <th colSpan={header.colSpan} key={column.id}>
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )}
+ </th>
- <th {...header.getHeaderProps()}>{cell.render('Header')}</th>
+ <th colSpan={header.colSpan} key={column.id}>
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )}
+ </th>
tsx
- <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
+ <td key={cell.id}>
+ {flexRender(
+ cell.column.columnDef.cell,
+ cell.getContext()
+ )}
+ </td>
- <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
+ <td key={cell.id}>
+ {flexRender(
+ cell.column.columnDef.cell,
+ cell.getContext()
+ )}
+ </td>
tsx
// in column definitions in this case
- Header: ({ getToggleAllRowsSelectedProps }) => (
- <input type="checkbox" {...getToggleAllRowsSelectedProps()} />
- ),
- Cell: ({ row }) => (
- <input type="checkbox" {...row.getToggleRowSelectedProps()} />
- ),
+ header: ({ table }) => (
+ <Checkbox
+ checked={table.getIsAllRowsSelected()}
+ indeterminate={table.getIsSomeRowsSelected()}
+ onChange={table.getToggleAllRowsSelectedHandler()}
+ />
+ ),
+ cell: ({ row }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ disabled={!row.getCanSelect()}
+ indeterminate={row.getIsSomeSelected()}
+ onChange={row.getToggleSelectedHandler()}
+ />
+ ),
// in column definitions in this case
- Header: ({ getToggleAllRowsSelectedProps }) => (
- <input type="checkbox" {...getToggleAllRowsSelectedProps()} />
- ),
- Cell: ({ row }) => (
- <input type="checkbox" {...row.getToggleRowSelectedProps()} />
- ),
+ header: ({ table }) => (
+ <Checkbox
+ checked={table.getIsAllRowsSelected()}
+ indeterminate={table.getIsSomeRowsSelected()}
+ onChange={table.getToggleAllRowsSelectedHandler()}
+ />
+ ),
+ cell: ({ row }) => (
+ <Checkbox
+ checked={row.getIsSelected()}
+ disabled={!row.getCanSelect()}
+ indeterminate={row.getIsSomeSelected()}
+ onChange={row.getToggleSelectedHandler()}
+ />
+ ),
tsx
- (rows: Row[], id: string, filterValue: any) => Row[]
+ (row: Row, id: string, filterValue: any) => boolean
- (rows: Row[], id: string, filterValue: any) => Row[]
+ (row: Row, id: string, filterValue: any) => boolean
This guide is a work in progress. Please consider contributing to it if you have time!
