TanStack Table - A Comprehensive Guide

Introduction

TanStack Table, formerly known as React Table, is a powerful and flexible table library for React. It offers a wide range of features that make it ideal for handling complex table data with ease. In this guide, we'll explore all the features that TanStack Table offers and how to implement them.

Getting Started with TanStack Table

  1. Installation To get started with TanStack Table, you need to install the necessary packages.

    npm install @tanstack/react-table
    
  2. Basic Setup Here's a basic setup to create a simple table:

    import React from 'react';
    import { useTable } from '@tanstack/react-table';
    
    const BasicTable = () => {
      const data = React.useMemo(() => [...], []);
      const columns = React.useMemo(() => [...], []);
    
      const tableInstance = useTable({ columns, data });
    
      return (
        <table>
          <thead>
            {tableInstance.headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th {...column.getHeaderProps()}>
                    {column.render('Header')}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {tableInstance.rows.map(row => {
              tableInstance.prepareRow(row);
              return (
                <tr {...row.getRowProps()}>
                  {row.cells.map(cell => (
                    <td {...cell.getCellProps()}>
                      {cell.render('Cell')}
                    </td>
                  ))}
                </tr>
              );
            })}
          </tbody>
        </table>
      );
    };
    
    export default BasicTable;
    

Key Features and Implementation

1. Pagination

Pagination allows users to navigate through large sets of data efficiently. TanStack Table supports both client-side and server-side pagination.

  • Client-Side Pagination:

    import { usePagination } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, usePagination);
    

    You'll need to provide buttons or a UI to change pages:

    <button onClick={() => tableInstance.previousPage()} disabled={!tableInstance.canPreviousPage}>
      Previous
    </button>
    <button onClick={() => tableInstance.nextPage()} disabled={!tableInstance.canNextPage}>
      Next
    </button>
    
  • Server-Side Pagination:

    For server-side pagination, you’ll need to handle the page changes with an API call:

    const fetchData = ({ pageIndex, pageSize }) => {
      // Fetch data from your API here
    };
    
    const tableInstance = useTable(
      { columns, data, manualPagination: true, pageCount: controlledPageCount },
      usePagination
    );
    

2. Sorting

Sorting allows users to order data based on specific columns.

  • Basic Sorting:

    import { useSortBy } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useSortBy);
    

    You can then add sorting functionality to your column headers:

    <th {...column.getHeaderProps(column.getSortByToggleProps())}>
      {column.render("Header")}
      <span>{column.isSorted ? (column.isSortedDesc ? " 🔽" : " 🔼") : ""}</span>
    </th>
    

3. Filtering

Filtering allows users to narrow down data based on specific criteria.

  • Column Filtering:

    import { useFilters } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useFilters);
    

    Implementing a simple text input filter:

    <input
      value={filterValue || ""}
      onChange={(e) => setFilter(e.target.value || undefined)}
    />
    

4. Global Filtering

Global filtering allows users to search across all columns.

  • Global Filter Implementation:

    import { useGlobalFilter } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useGlobalFilter);
    
    const handleGlobalFilterChange = (e) => {
      setGlobalFilter(e.target.value || undefined);
    };
    
    return (
      <input value={globalFilter || ""} onChange={handleGlobalFilterChange} />
    );
    

5. Column Resizing

Column resizing gives users the ability to adjust the width of columns.

  • Column Resizing Implementation:

    import { useResizeColumns } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useResizeColumns);
    
    return (
      <th {...column.getHeaderProps()} style={{ width: column.width }}>
        {column.render("Header")}
        <div {...column.getResizerProps()} className="resizer" />
      </th>
    );
    

6. Row Selection

Row selection allows users to select one or more rows.

  • Row Selection Implementation:

    import { useRowSelect } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useRowSelect, (hooks) => {
      hooks.visibleColumns.push((columns) => [
        {
          id: "selection",
          Header: ({ getToggleAllRowsSelectedProps }) => (
            <input type="checkbox" {...getToggleAllRowsSelectedProps()} />
          ),
          Cell: ({ row }) => (
            <input type="checkbox" {...row.getToggleRowSelectedProps()} />
          ),
        },
        ...columns,
      ]);
    });
    

7. Virtualized Rows

Virtualization is crucial for handling large datasets efficiently by only rendering rows currently visible in the viewport.

  • Virtualized Rows Implementation:

    import { useVirtual } from "@tanstack/react-table";
    
    const rowVirtualizer = useVirtual({
      size: tableInstance.rows.length,
      parentRef: tableContainerRef,
    });
    
    return (
      <div ref={tableContainerRef} style={{ height: "400px", overflowY: "auto" }}>
        <div style={{ height: rowVirtualizer.totalSize }}>
          {rowVirtualizer.virtualItems.map((virtualRow) => {
            const row = tableInstance.rows[virtualRow.index];
            return (
              <div
                key={row.id}
                ref={virtualRow.measureRef}
                style={{ transform: `translateY(${virtualRow.start}px)` }}
              >
                <tr {...row.getRowProps()}>
                  {row.cells.map((cell) => (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  ))}
                </tr>
              </div>
            );
          })}
        </div>
      </div>
    );
    

8. Custom Rendering

Custom rendering allows you to define how data should be displayed in the table.

  • Cell Rendering:

    const columns = React.useMemo(
      () => [
        {
          Header: "Name",
          accessor: "name",
          Cell: ({ value }) => <strong>{value}</strong>,
        },
      ],
      []
    );
    

    You can also use conditional rendering based on cell values.

9. Grouping

Grouping allows you to group rows based on specific columns.

  • Grouping Implementation:

    import { useGroupBy } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useGroupBy);
    
    const columns = React.useMemo(
      () => [
        {
          Header: "Group",
          accessor: "group",
          aggregate: "count",
          Aggregated: ({ value }) => `${value} items`,
        },
      ],
      []
    );
    

10. Column Reordering

Column reordering allows users to drag and drop columns to reorder them.

  • Column Reordering Implementation:

    import { useColumnOrder } from "@tanstack/react-table";
    
    const tableInstance = useTable({ columns, data }, useColumnOrder);
    
    const changeOrder = () => {
      tableInstance.setColumnOrder(["name", "age", "status"]);
    };
    

Conclusion

TanStack Table is a feature-rich library that can handle various complex table operations with ease. This guide covers the essential features you might need in your projects. With the flexibility TanStack Table offers, you can customize it to suit your specific requirements.

For more advanced use cases, refer to the official TanStack Table documentation and explore additional plugins and hooks.

0
Subscribe to my newsletter

Read articles from Abhijeet Maharana directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abhijeet Maharana
Abhijeet Maharana

I am a skilled Full Stack Developer with 3+ years of experience in frontend development, specializing in React, Next.js, and D3.js. Currently expanding my expertise in backend technologies like Node.js and MongoDB, along with cloud and DevOps. I’m driven to create seamless, high-performance web applications that provide exceptional user experiences.