5

I'm using @tanstack/react-table v8, and I want to have some icons and buttons in one of my table row cells. Looking at the docs I can use a display column for this:

Display columns do not have a data model which means they cannot be sorted, filtered, etc, but they can be used to display arbitrary content in the table, eg. a row actions button, checkbox, expander, etc.

The docs also mention this about custom rendering of cell content: By default, columns cells will display their data model value as a string. You can override this behavior by providing custom rendering implementations. ... You can provide a custom cell formatter by passing a function to the cell property ...

The docs show this example for custom rendering of a cell:

columnHelper.accessor('firstName', {
  cell: props => <span>{props.getValue().toUpperCase()}</span>,
})

So, I have defined a display column using ColumnHelper:

columnHelper.display({
  id: "actions",
  cell: (props) => (
    <div className="w-10 h-10 bg-red">
      <span>actions?</span>
    </div>
  ),
}),

How do I access this render function when creating the table? I'm creating the table body as follows (the table variable is returned by the useReactTable hook):

<tbody>
  {table.getRowModel().rows.map((row, index) => (
    <tr className={classNames(index % 2 !== 0 && "bg-tableRowGray")}>
      {row.getAllCells().map((cell) => (
        <td>{cell.getValue()}</td>
      ))}
    </tr>
  ))}
</tbody>

cell.getValue() and cell.renderValue() do not call the custom render function and I don't see any other render functions on the cell object. Am I just overlooking something really simple here?

Thijs
  • 587
  • 5
  • 16

2 Answers2

5

Turns out I was overlooking something simple. @tanstack/react-table exports a flexRender function which is used to render the cell, e.g.

import {flexRender} from "@tanstack/react-table";

...

<tbody>
  {table.getRowModel().rows.map((row, index) => (
    <tr className={classNames(index % 2 !== 0 && "bg-tableRowGray")}>
      {row.getAllCells().map((cell) => (<td>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>))}
    </tr>
  ))}
</tbody>

Thijs
  • 587
  • 5
  • 16
1

I had the same issue while trying to render custom components for each cell and this is the solution that I came up with:

    const cols = [
          {
            header: "Actions",
            cell: (row) => {
              return (
                <button 
                  // onClick={a function based on the cell value}
                >
                  {row.getValue() as ReactNode}
                </button>
              );
            },
            accessorKey: "actions",
          },
        ],

As you can see the columns array that is passed gets a cell prop. Inside it, you can pass a function that return your desired JSX component.

Amin Jafarlou
  • 336
  • 1
  • 10