TanStack Table

repository·main·Indexed 12 days ago

https://github.com/TanStack/table

A headless UI library for building highly customizable datagrids with logic and state management for sorting, filtering, grouping, and pagination. Framework-agnostic and compatible with React, Vue, Svelte, Angular, Solid, and others. Version 9 introduces TanStack Intent for AI coding agent guidance and requires stable references for data and columns.

Tokens
766.8K
Snippets
2.3K
Records
3.1K
Agent score
95%

What's inside TanStack Table

  1. Overview of @tanstack/lit-table

    main
    The @tanstack/lit-table package provides integration for TanStack Table within the Lit framework. It includes specialized classes like TableController for managing table state and lifecycle, and a SubscribeDirective for reacting to table changes. It also provides utility functions like flexRender to handle rendering logic within Lit components.
  2. Overview of TanStack Table

    main

    TanStack Table is a headless table library designed for building powerful datagrids. Because it is 'headless', it provides the logic, state management, and features (like sorting, filtering, and grouping) without providing any UI. This gives developers full control over the markup, styles, and component structure.

    Key features include:

    • Framework-agnostic core: Works with React, Preact, Vue, Solid, Svelte, Angular, Ember, Lit, Alpine, and Octane.
    • 100% Customizable: You bring your own UI and components.
    • Advanced Features: Supports sorting, filtering, grouping, aggregation, and row selection.
    • Performance: Lightweight, virtualizable, and optimized for server-side workflows.
  3. Migrating to TanStack Table V9 (Svelte) Overview

    main

    TanStack Table V9 introduces significant architectural changes compared to V8, focusing on performance, type-safety, and composability. While the core headless model, column definitions (accessorKey, accessorFn, header, cell, footer), and rendering patterns remain familiar, the underlying state management and feature registration systems have been overhauled.

    Key Changes in V9:

    • State Management: Moved from V8 writable-store patterns to a foundation of TanStack Store atoms and Svelte 5 runes.
    • Feature-Based Architecture: Features (like sorting, filtering, or pagination) must be explicitly registered. This enables better tree-shaking, as unused feature code is not included in your bundle.
    • Type-Safety: Replaces global declaration merging with per-table meta types (tableMeta, columnMeta, filterMeta).
    • Performance: Improved memory usage (up to 90% savings in large tables) and faster client-side row models (40-70% speed improvements).
    • Modern Builds: The library is now ESM-only and targets ES2022.
  4. Performance improvements in TanStack Table v9

    main

    TanStack Table v9 introduced significant performance optimizations over v8, particularly in row model processing, grouping, sorting, and filtering. Key architectural changes include a prototype-based row architecture (sharing a single prototype instead of creating per-row closures) and optimized loop patterns (e.g., using indexed sweeps instead of for...of).

    Key Performance Wins (at 400k rows):

    • Core Row Model: ~72% reduction in processing time.
    • Grouping: ~47–58% reduction.
    • Sorting (Alphanumeric/Datetime): ~51–61% reduction.
    • Filtering: ~35–45% reduction.
    • Faceting (scoreMin/Max): ~72% reduction.
    • Expanding (Tree Data): ~73% reduction.
    • Selection: ~58% reduction.
  5. Explore TanStack Table Interfaces

    main

    The TanStack Table API is composed of a wide range of interfaces that define the structure and behavior of the table, its columns, rows, cells, and headers. These interfaces are categorized by their functional area:

    • Core Table & State: Interfaces like Table_Table, TableOptions_Table, and various TableState_* interfaces define the central table instance and its configuration.
    • Columns: Interfaces such as Column_Column, ColumnDef_*, and ColumnPinningState manage column definitions, visibility, resizing, and ordering.
    • Rows & Cells: Interfaces like Row_Row, Cell_Cell, and Row_RowSelection handle data rows, cell-level interactions (selection, spanning), and row-level features (expanding, pinning).
    • Headers: Interfaces like Header_Header and HeaderGroup manage the visual and logical structure of the table header.
    • Aggregation: Interfaces such as AggregationFnDef and AggregationValueContext provide tools for summarizing data.
    • Row Models: Various CachedRowModel_* interfaces define how data is presented after filtering, sorting, or pagination.
    • Filtering & Sorting: Interfaces like FilterFn and SortFn define the logic for data manipulation.
  6. Use the @tanstack/vue-table package

    main
    The @tanstack/vue-table package provides the Vue-specific implementation of TanStack Table. It includes hooks for creating table instances, type definitions for column definitions and table state, and utility functions like flexRender to handle custom cell and header rendering within Vue templates.
  7. Use @tanstack/alpine-table

    main

    The @tanstack/alpine-table package provides integration for using TanStack Table within Alpine.js applications. It exposes core functions and type aliases to bridge the table logic with Alpine's reactive system.

    Key components include:

    • createTable: The primary function for initializing a table instance.
    • createTableHook: Used for creating hooks to integrate table state with Alpine.
    • flexRender: A utility for rendering cell content, supporting both simple values and complex component-based rendering.
  8. What is Headless UI and how does TanStack Table work?

    main

    TanStack Table is a headless UI library. Unlike pre-built table components (e.g., AG Grid) that provide ready-to-use markup and styles, a headless library provides only the logic, state, processing, and APIs.

    Key Characteristics:

    • Agnostic: ~95% of the source code is framework-agnostic TypeScript. It works with any JavaScript library, component library, or design system (Tailwind, Bootstrap, Material UI, etc.).
    • Full Control: You are responsible for the markup and styling. You create a table instance and use its state and APIs (like getHeaderGroups() or getRowModel().rows) to render your own HTML.
    • Separation of Concerns: The library handles complex data processing, state management, and business logic, while you handle the visual implementation (the "higher-cardinality decisions").
  9. What is Faceting in TanStack Table?

    main

    Faceting is a mechanism used to derive metadata for building filtering interfaces (like checkboxes, sliders, or autocomplete menus). It answers questions about the available data such as:

    • Which values are available in a column?
    • How often does each value occur (counts)?
    • What are the minimum and maximum values in a numeric range?
    • Which rows should be used for custom facet calculations?

    Key Distinctions:

    • Faceting vs. Filtering: Filtering determines which rows remain in the table. Faceting provides the choices for those filters. A facet shows available options based on other active filters, allowing users to see what other options exist even after they have selected a value in the current column.
    • Faceting vs. Row Aggregation: Row aggregation (like sum or average) computes summary values for display in footers or grouped rows. Faceting produces metadata specifically for filter controls and does not use a column's aggregationFn.
  10. What is Faceting and how does it differ from Aggregation?

    main

    Faceting derives metadata used to build filtering interfaces (e.g., available values, occurrence counts, or numeric ranges). It answers: "Which filtering choices remain?"

    Key Distinctions:

    • Faceting vs. Filtering: Filtering determines which rows remain in the table. Faceting provides the values/counts used to build the UI that performs the filtering.
    • Faceting vs. Row Aggregation: Aggregation computes summary values (sum, average) for display in footers or grouped rows. Faceting produces metadata for filter controls. Faceted counts do not use a column's aggregationFn and do not create aggregate rows.
    • Reactive Behavior: A column's faceted model includes rows that pass every active filter except that column's own filter. This allows a user to see alternative options in a facet even after they have selected a value for it, while still allowing other facets to narrow the results.
  11. What is a TanStack Table instance?

    main
    TanStack Table is a headless UI library. A "table instance" is not a literal HTML <table> element, but a core table object that coordinates table state and APIs. It is the central object used to read and mutate table state and is the primary interface for rendering your UI. You create it using your framework's specific table creation function (e.g., useTable, createTable, injectTable, or constructTable).
  12. Consume table context using AppTable and useTableContext

    main

    To access the table state or methods in child components, use the useTableContext hook provided by your factory. For this to work, the child components must be wrapped in the corresponding provider (e.g., table.AppTable).

    AppTable can be used in two ways:

    1. Standard usage: Pass ordinary JSX children. The children will have access to the table context.
    2. Selector usage: Pass a selector function and a function as children. The function child will receive the specific slice of state returned by the selector.
    // 1. Standard usage with useTableContext
    function RowCount() {
      const table = useTableContext()
      return <output>{table.getRowModel().rows.length}</output>
    }
    
    function MyTable({ data, columns }) {
      const table = useAppTable({ data, columns })
      return (
        <table.AppTable>
          <RowCount />
        </table.AppTable>
      )
    }
    
    // 2. Selector usage for specific state slices
    <table.AppTable selector={(state) => state.rowSelection}>
      {(rowSelection) => <output>{Object.keys(rowSelection).length}</output>}
    </table.AppTable>