Tabler React 2 Docs
Tables
Tables
Tables are used to display tabular data. They can be used to display data in a table, list, or any other tabular data.
Signature
import { Table } from "tabler-react-2";
<Table {...props} />;Props
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
columns | Yes | Column | An array of column objects. | |
data | Yes | Array | An array of data objects. |
For all of the tables on this page, we will use this list of congress people. (click to expand)
[{"name": "Ed Case","email": "ed.case@mail.house.gov","party": "democrat","region": {"state": "Hawaii","abbr": "HI","district": "1st"},"website": "https://case.house.gov"},{"name": "Mike Carey","email": "mike.carey@mail.house.gov","party": "republican","region": {"state": "Ohio","abbr": "OH","district": "15th"},"website": "https://carey.house.gov"},{"name": "Andrew Clyde","email": "andrew.clyde@mail.house.gov","party": "republican","region": {"state": "Georgia","abbr": "GA","district": "9th"},"website": "https://clyde.house.gov"},{"name": "Angie Craig","email": "angie.craig@mail.house.gov","party": "democrat","region": {"state": "Minnesota","abbr": "MN","district": "2nd"},"website": "https://craig.house.gov"},{"name": "Rick Crawford","email": "rick.crawford@mail.house.gov","party": "republican","region": {"state": "Arkansas","abbr": "AR","district": "1st"},"website": "https://crawford.house.gov"},{"name": "Jared Golden","email": "jared.golden@mail.house.gov","party": "democrat","region": {"state": "Maine","abbr": "ME","district": "2nd"},"website": "https://golden.house.gov"},{"name": "Dusty Johnson","email": "dusty.johnson@mail.house.gov","party": "republican","region": {"state": "South Dakota","abbr": "SD","district": "At-Large"},"website": "https://dustyjohnson.house.gov"},{"name": "Susie Lee","email": "susie.lee@mail.house.gov","party": "democrat","region": {"state": "Nevada","abbr": "NV","district": "3rd"},"website": "https://susielee.house.gov"}]
Basic Usage
The Table component is used to display tabular data. It takes an array of objects as a prop called columns. Each object in the array represents a column in the table. The object should have a label property that is the text to display in the column header, and a accessor property that is the key of the object to use for the data in that column.
The Table component also takes a data prop that is an array of objects. Each object in the array represents a row in the table. The object should have a key for each column in the columns array.
import congressPeople from "./congressPeople.json";
<Table columns={[ { label: "Name", accessor: "name", sortable: true }, { label: "Party", accessor: "party", render: (party) => ( <> <img src={`/${party}.png`} style={{ width: 25 }} /> {party} </> ), }, { label: "State", accessor: "region.state", }, { label: "District", accessor: "region.district", render: (district, row) => ( <> <span className="text-secondary">{row.region.abbr}</span> {district} </> ), }, { label: "Email", accessor: "email", className: "text-secondary", render: (email) => ( <a href={`mailto:${email}`} className="text-reset"> <IconMail strokeWidth={1.5} /> </a> ), }, ]} data={congressPeople}/>;Constructing the columns array
The columns prop is an array of objects. Each object represents a column in the table. It has the following properties:
| Prop | Required | Type | Default | Description |
|---|---|---|---|---|
label | Yes | String | The text to display in the column header. | |
accessor | Yes | String | The key of the object to use for the data in that column. | |
className | No | String | Additional CSS classes to apply to the column. | |
render | No | Function | Custom render function for the cell content. | |
sortable | No | Boolean | false | Whether the column is sortable. |
sortFn | No | Function | Custom sorting function. |
accessor
The accessor prop is the key of the object to use for the data in that column. It is a string that corresponds to the key of the object in the data array. It supports nested keys using dot notation.
Use the accessor prop to render simple text in your table. If you need any customization, use the render prop as well as accessor.
Setting the accessor prop to the string 'name' will return the values
<Table columns={[{ label: "Name", accessor: "name" }]} data={congressPeople} />You can access the nested keys of (in this case) the region object by using dot notation. For example, setting the accessor prop to region.district will return the values
<Table columns={[{ label: "District", accessor: "region.district" }]} data={congressPeople}/>To access other keys in the object (combining multiple keys in a single cell), you cannot use the accessor. Still provide something to the accessor prop so there is not an error, but use the render prop to display the content.
render
The render prop is an optional function that will be called with the value of the cell and the row object.
It has the following signature:
render(value: any, row: object): React.ReactNode;Where value is the value provided by the accessor and row is the entire row.
So, to render the congress person's party with the symbol, (assuming /democrat.png and /republican.png exist), you can use the render prop to display the party.
<Table columns={[ { label: "Person's Party", accessor: "party", render: (partyFromAccessor) => ( <> <img src={`/${partyFromAccessor}.png`} style={{ width: 25 }} /> {partyFromAccessor} </> ), }, ]} data={congressPeople}/>To include other values from the row in the cell, you can use the second argument passed to the render function. In this case, we will leave the accessor the same, so the first argument will be either "democrat" or "republican". The second argument is the entire row object that we will pull the region.state value from.
<Table columns={[ { label: "Person's Party", accessor: "party", render: (party, row) => ( <> {party} ({row.region.state}) </> ), }, ]} data={congressPeople}/>sortable
The sortable prop is an optional boolean that determines whether the column is sortable. If it is set to true, the column will be sortable. The default value is false. It will sort based on the value of the column's accessor.
<Table columns={[ { label: "Name", accessor: "name", }, { label: "Party", accessor: "party", render: ..., sortable: true, }, { label: "State", accessor: "region.state", sortable: true, }, ]} data={congressPeople}/>You can also pass a custom sorting function to the sortFn prop. The sorting function should take two arguments and return -1, 0, or 1. The first argument is the value of the first cell, and the second argument is the value of the second cell.
The default sorting function is
const defaultSortFn = (a, b) => { if (a === b) return 0; return a > b ? 1 : -1;};If, for some reason, you wanted to sort by the length of the name, you could do the following:
const customSortFn = (a, b) => { if (a.length === b.length) return 0; return a.length > b.length ? 1 : -1;};
<Table columns={[ { label: "Name", accessor: "name", sortFn: customSortFn, sortable: true, }, ]} data={congressPeople}/>;Note: Sorting only works for the data in the table. If, for example, you have thousands of rows and are only rendering a few, you will need to handle the sorting yourself, outside of the table. Incorporating internal pagination that supports sorting is a planned feature but not yet implemented.
External ordering
You can control ordering from the parent (e.g., server-side sort) and still use the table’s sortable headers. Provide the props below. When controlled, the table will not sort your data; it assumes you already passed rows in the desired order.
- orderBy: accessor of the active column
- order: either
"asc"or"desc" - onSetOrder: called with
(orderBy, order)when the user clicks a header
// Parent controls ordering and paginationconst [orderBy, setOrderBy] = useState('name');const [order, setOrder] = useState('asc');const [page, setPage] = useState(1);const [size, setSize] = useState(10);
const ordered = [...allRows].sort((a, b) => { const av = orderBy.split('.').reduce((acc, k) => acc?.[k], a); const bv = orderBy.split('.').reduce((acc, k) => acc?.[k], b); if (av === bv) return 0; const cmp = av > bv ? 1 : -1; return order === 'asc' ? cmp : -cmp;});
const start = (page - 1) * size;const currentData = ordered.slice(start, start + size);
<Table columns={columns} data={currentData} showPagination page={page} size={size} totalRows={allRows.length} orderBy={orderBy} order={order} onSetOrder={(by, dir) => { setOrderBy(by); setOrder(dir); }} onSetPage={setPage} onSetSize={(n) => { setPage(1); setSize(n); }}/>;Pagination
The Table supports built-in pagination UI. Enable it with showPagination.
- showPagination: toggles the pagination controls
- defaultRowsPerPage: initial rows per page for internal mode
- pageSizeOptions: selectable page sizes (default
[10, 25, 50, 100])
<Table columns={columns} data={rows} showPagination defaultRowsPerPage={10} pageSizeOptions={[10, 25, 50, 100]}/>External pagination
You can also fully control pagination from the parent (e.g., server-side paging) while keeping the same UI. Provide the controlled props and callbacks below. When any controlled pagination prop is provided, the table does not slice your data and instead assumes data already contains the current page.
- page: current page (1-based)
- size: current page size
- totalRows: total available row count used for page count and the “Showing … of …” text
- onSetPage: called with next page (1-based)
- onSetSize: called with next page size
Aliases are supported for compatibility: rowsPerPage, onPageChange, onRowsPerPageChange.
// Parent controls the tableconst [page, setPage] = useState(1);const [rowsPerPage, setRowsPerPage] = useState(10);const totalRows = allRows.length; // from your API
// Only pass the current slice to the tableconst start = (page - 1) * rowsPerPage;const currentData = allRows.slice(start, start + rowsPerPage);
<Table columns={columns} data={currentData} showPagination page={page} size={rowsPerPage} totalRows={totalRows} onSetPage={setPage} onSetSize={(n) => { setPage(1); setRowsPerPage(n); }}/>;If you don’t supply these controlled props, the table falls back to its internal pagination state, preserving backwards compatibility.
useTable hook
For async workflows, use the helper hook to centralize loading, pagination, count, and ordering while preserving the Table’s controlled API.
import { useEffect, useState } from 'react';import { Table, useTable } from 'tabler-react-2';
function PeopleTable() { const [rows, setRows] = useState([]); const { tableProps, setLoading, setPage, setCount, setOrder } = useTable({ autoLoading: false, onPageChange: async (page, size, sort) => { setLoading(true); try { // fetch your data here using page, size, and sort const res = await fetchPeople({ page, size, sort }); setRows(res.items); setCount(res.total); } finally { setLoading(false); } }, onSortChange: async (by, dir) => { // optionally kick off a fetch based on new sort // setOrder(by, dir) is already called for you }, });
useEffect(() => { // initial load setPage(1); }, [setPage]);
return <Table {...tableProps} columns={[ { label: 'Name', accessor: 'name', sortable: true }, { label: 'Party', accessor: 'party', sortable: true }, { label: 'State', accessor: 'region.state', sortable: true }, ]} data={rows} />;}The hook returns:
- tableProps: spread onto
<Table />to enable controlled pagination, ordering, and loading - setLoading, setPage, setCount: imperative helpers for async flows
- Also available: page, size, count, orderBy, order, setSize, setOrder