TanStack Table: Expand only one cell on click without expanding the entire row
10:22 28 Apr 2024

I’m using TanStack Table and have multiple expandable cells within the same row.

When I click one expand button, all expandable cells in that row are triggered.

How can I make only the clicked cell expand independently, without affecting other cells in the row?

Whatever I've tried so far is in this codesandbox.

App.tsx

import {
  ColumnDef,
  ColumnFiltersState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from "@tanstack/react-table";
import { useState } from "react";

import { expandableColumn, expandableData } from "./column-data";

interface DataTableProps {
  columns: ColumnDef[];
  data: TData[];
  renderSubComponent: (props: { row: Row }) => React.ReactElement;
  getRowCanExpand: (row: Row) => boolean;
}

const renderSubComponent = ({ row }: { row: Row }) => {
  return (
    
      {JSON.stringify(row.original, null, 2)}
    
); }; export function ExpandableTable({ columns, data, renderSubComponent, getRowCanExpand, }: DataTableProps) { const [columnVisibility, setColumnVisibility] = useState({}); const table = useReactTable({ data, columns, getRowCanExpand, state: { columnVisibility, }, autoResetPageIndex: false, enableRowSelection: true, onColumnVisibilityChange: setColumnVisibility, getCoreRowModel: getCoreRowModel(), getExpandedRowModel: getExpandedRowModel(), }); return (
{/* */}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( ); })} ))} {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( <> {row.getVisibleCells().map((cell) => ( ))} {row.getIsExpanded() && ( {/* 2nd row is a custom 1 cell row */} )} )) ) : ( )}
{header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )}
{flexRender( cell.column.columnDef.cell, cell.getContext() )}
{renderSubComponent({ row })}
No results.
); } export default function App() { return (

Expand Table Example

Start editing to see some magic happen!

true} />
); }

column.tsx

export const expandableColumn = [
  {
    accessorKey: "firstName",
    header: "First Name",
    cell: ({ row, getValue }) => (
      
{row.getCanExpand() ? ( ) : ( "πŸ”΅" )} {getValue()}
), footer: (props) => props.column.id, }, { accessorFn: (row) => row.lastName, id: "lastName", cell: ({ row, getValue }) => (
{row.getCanExpand() ? ( ) : ( "πŸ”΅" )} {getValue()}
), header: () => Last Name, footer: (props) => props.column.id, }, { accessorKey: "age", header: () => "Age", footer: (props) => props.column.id, }, { accessorKey: "visits", header: () => Visits, footer: (props) => props.column.id, }, { accessorKey: "status", header: "Status", footer: (props) => props.column.id, }, { accessorKey: "progress", header: "Profile Progress", footer: (props) => props.column.id, }, ]; export const expandableData = [ { firstName: "Marquis", lastName: "Runolfsdottir", age: 36, visits: 322, progress: 46, status: "single", }, { firstName: "Hayden", lastName: "Ritchie", age: 35, visits: 208, progress: 79, status: "relationship", }, { firstName: "Destany", lastName: "Boehm", age: 37, visits: 752, progress: 97, status: "relationship", }, { firstName: "Kale", lastName: "Johnston", age: 36, visits: 378, progress: 13, status: "complicated", }, { firstName: "Maybell", lastName: "Brown", age: 16, visits: 783, progress: 76, status: "complicated", }, { firstName: "Emelia", lastName: "Cronin", age: 30, visits: 655, progress: 96, status: "complicated", }, { firstName: "Kali", lastName: "Marvin", age: 18, visits: 926, progress: 57, status: "complicated", }, { firstName: "Khalid", lastName: "Robel", age: 34, visits: 671, progress: 100, status: "complicated", }, { firstName: "Zena", lastName: "Hilll", age: 34, visits: 934, progress: 18, status: "single", }, { firstName: "Hiram", lastName: "Koss", age: 12, visits: 757, progress: 44, status: "relationship", }, ];
reactjs react-table tanstack-table react-table-v8