Published on

Passing Props to react-table ColumnDef in ShadCN Data Table

Authors
  • Name
    Ripal & Zalak
    Twitter

When working with ShadCN Data Table built on top of react-table (TanStack Table), you might encounter challenges when passing dynamic props, such as URL search parameters, to the ColumnDef definitions. In this blog, we’ll explore a robust way to achieve this functionality.


The Challenge

You want to pass a parameter, such as a URL search parameter, to dynamically customize your column definitions (columns.tsx) in a ShadCN Data Table. For instance, consider the following use case:

  • You want the status column to include a hyperlink that incorporates a dynamic owner parameter from the URL search params.

Here’s an example of the structure:

page.tsx

import { Payment, columns } from './columns'
import { DataTable } from './data-table'

async function getData(): Promise<Payment[]> {
  return [
    {
      id: '728ed52f',
      amount: 100,
      status: 'pending',
      email: 'm@example.com',
    },
    {
      id: '1234ffff',
      amount: 125,
      status: 'done',
      email: 'm@example.com',
    },
  ]
}

type Props = {
  searchParams: {
    owner: string | undefined
  }
}

export default async function DemoPage({ searchParams }: Props) {
  const owner = searchParams.owner
  console.log(owner)
  const data = await getData()

  return (
    <div className="container mx-auto py-10">
      <DataTable columns={columns} data={data} />
    </div>
  )
}

columns.tsx

'use client'

import { ColumnDef } from '@tanstack/react-table'
import Link from 'next/link'

export type Payment = {
  id: string
  amount: number
  status: 'pending' | 'processing' | 'success' | 'failed'
  email: string
}

export const columns: ColumnDef<Payment>[] = [
  {
    accessorKey: 'status',
    header: 'Status',
    cell: ({ row }) => <Link href="http://example.com/owner">{row.getValue('status')}</Link>,
  },
  {
    accessorKey: 'email',
    header: 'Email',
  },
  {
    accessorKey: 'amount',
    header: 'Amount',
  },
]

Currently, the owner parameter is hardcoded in the columns.tsx file. Our goal is to make it dynamic.


The Solution: Use Table Meta

React-table allows you to pass a meta property when creating the table. You can store dynamic props, such as the owner parameter, in this meta property and access it in your column definitions.

Step 1: Pass meta to the Table

Update the DataTable component to pass the owner parameter as part of the meta property:

import { useReactTable } from '@tanstack/react-table'

type DataTableProps = {
  columns: ColumnDef<Payment>[]
  data: Payment[]
  owner: string | undefined
}

export function DataTable({ columns, data, owner }: DataTableProps) {
  const table = useReactTable({
    data,
    columns,
    meta: {
      owner: owner,
    },
  })

  return <div>{/* Render table here */}</div>
}

Step 2: Access meta in Column Definitions

You can now access the owner parameter inside the columns definition using table.options.meta.

import { ColumnDef } from '@tanstack/react-table'
import Link from 'next/link'

export const columns: ColumnDef<Payment>[] = [
  {
    accessorKey: 'status',
    header: 'Status',
    cell: ({ row, table }) => (
      <Link href={`http://example.com/${(table.options.meta as any)?.owner}`}>
        {row.getValue('status')}
      </Link>
    ),
  },
  {
    accessorKey: 'email',
    header: 'Email',
  },
  {
    accessorKey: 'amount',
    header: 'Amount',
  },
]
  • table.options.meta: This is where the owner parameter is stored.
  • Dynamic URL: The owner parameter is dynamically inserted into the URL for the status column.

Step 3: Use the Updated DataTable

Finally, update the DemoPage component to pass the owner parameter:

export default async function DemoPage({ searchParams }: Props) {
  const owner = searchParams.owner
  const data = await getData()

  return (
    <div className="container mx-auto py-10">
      <DataTable columns={columns} data={data} owner={owner} />
    </div>
  )
}

Benefits of This Approach

  1. Reusability: The columns definition becomes dynamic and reusable for different owner parameters.
  2. Cleaner Code: Avoids the need to redefine columns as a function.
  3. Flexibility: You can pass multiple dynamic props through the meta property if needed.

Conclusion

Using meta in react-table is a powerful way to pass dynamic props, such as URL search parameters, to your ColumnDef definitions in ShadCN Data Table. This approach ensures clean, reusable, and flexible code.

Let me know if you have any questions or need further clarification!