Defining Columns and Rendering Rows
Configure column definitions with accessors, headers, and cell renderers to display your data.
Defining Columns and Rendering Rows is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The ColumnDef Type
Every column in TanStack Table is described by a ColumnDef object. The two most important fields are accessorKey (the property name on your data object) and header (the column label string or render function).
The accessorKey approach is ideal for flat data; complex or computed values need accessorFn.
accessorKey vs accessorFn
When your data has a direct property like name or email, use accessorKey: 'name'. When you need to compute a value (e.g., combining firstName and lastName), use accessorFn: row => row.firstName + ' ' + row.lastName.
Both are fully typed when you provide the row data generic to ColumnDef.
Custom Cell Rendering with cell
The cell field in a ColumnDef accepts a function that receives the cell context and returns JSX. This is how you render badges, buttons, images, or any custom UI inside a cell.
For plain text values, cell.renderValue() is sufficient. For anything richer, destructure info from cell.getContext().
Building the Columns Array
Define your columns outside the component to avoid recreating them on every render. Pass the array to useReactTable alongside your data and getCoreRowModel.
TypeScript will infer column types when you annotate ColumnDef with your data type, giving you autocomplete on accessorKey values.
getCoreRowModel Explained
getCoreRowModel is a factory function imported from @tanstack/react-table. You pass its return value to useReactTable to tell the instance how to build the basic list of rows from your data array.
Additional row models (sorted, filtered, paginated) are layered on top by passing extra model factories.
Rendering thead with getHeaderGroups
Call table.getHeaderGroups() and map over the result to render your thead. Each header group has a headers array; each header has a column definition and an id.
Use flexRender(header.column.columnDef.header, header.getContext()) to render the header content, whether it is a string or a JSX-returning function.
Rendering tbody with getRowModel
Call table.getRowModel().rows and map each row to a tr element. Inside, call row.getVisibleCells() and map each cell to a td.
Use flexRender(cell.column.columnDef.cell, cell.getContext()) to render cell content, respecting any custom cell renderer defined in the column.
The flexRender Utility
flexRender is a helper that accepts either a React component, a function returning JSX, or a plain value, and renders it consistently. It allows column definitions to use either simple strings or full render functions for headers and cells.
This unified API means you do not need to check the type of the definition before rendering.
Cell Context and renderValue
cell.renderValue() returns the raw accessor value formatted as a string. For more control, cell.getContext() provides the full rendering context including the row, column, table instance, and the raw value.
Custom cell renderers use the context to access related row data beyond the single accessor value.
Column Pinning and Meta
Each ColumnDef accepts a meta field where you can attach arbitrary metadata like isSticky: true or alignment: 'right'. Access it in your renderer via column.columnDef.meta.
For pinning columns to the left or right, TanStack Table provides column pinning state and helper methods on the column object.
Putting It All Together
Define ColumnDef array with accessorKey, header, and optional cell. Call useReactTable with data, columns, and getCoreRowModel. Map getHeaderGroups for thead and getRowModel().rows for tbody, using flexRender to render each header and cell.
This minimal setup gives you a fully functional, fully custom-styled table.
accessorKey vs accessorFn
When should you use accessorFn instead of accessorKey in a TanStack Table column definition?
Lesson Recap
Define columns using ColumnDef with accessorKey for direct fields or accessorFn for computed values. Pass columns and getCoreRowModel to useReactTable, then render with getHeaderGroups for headers and getRowModel().rows for body rows.
The flexRender utility handles both string and function-based header and cell definitions uniformly.
Frequently asked questions
Is the “Defining Columns and Rendering Rows” lesson free?
Yes — the full text of “Defining Columns and Rendering Rows” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Defining Columns and Rendering Rows”?
Configure column definitions with accessors, headers, and cell renderers to display your data. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Defining Columns and Rendering Rows” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- TanStack Table Philosophy and Headless Design
- Defining Columns and Rendering Rows
- Sorting, Filtering, and Pagination
- Row Selection and Virtualized Tables