React Final Table
A headless UI library for React tables, inspired by
react-table but with Typescript
support built in and a simpler API.
Features
- Type safe
- Global row filtering
- Row selection
- Custom column rendering
- Column sorting
- Data memoization for performance
- Zero dependencies
Motivation
While there are a plethora of table libraries available for every framework,
most are opinionated about the UI. This is a minimal, type-safe headless UI
library that you can plugin to whatever frontend framework you're using, as long
as you're using React 16 and functional components.
Install
npm install react-final-table
Hooks
useTable
This is the main hook exposed by the library and should be your entrypoint for
any table functionality. Only columns
and data
are required as arguments:
const {
headers,
rows,
selectRow,
selectedRows
} = useTable(columns, data, {
selectable?: boolean,
filter?: (rows: RowType<T>[]) => RowType<T>[],
});
Basic example
import { useTable } from 'react-final-table';
const columns = [
{
name: 'firstName',
label: 'First Name',
render: ({ value }) => <h1>{value}</h1>, // optional
},
{
name: 'lastName',
label: 'Last Name',
},
];
const data = [
{
firstName: 'Frodo',
lastName: 'Baggins',
},
{
firstName: 'Samwise',
lastName: 'Gamgee',
},
];
const MyTable = () => {
const { headers, rows } = useTable(columns, data);
return (
<table>
<thead>
<tr>
{headers.map((header, idx) => (
<th key={idx}>{header.label}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, idx) => (
<tr key={idx}>
{row.cells.map((cell, idx) => (
<td key={idx}>{cell.render()}</td>
))}
</tr>
))}
</tbody>
</table>
);
};
Advanced Example
import React, { useMemo } from 'react';
import { useTable } from 'react-final-table';
const columns = [
{ name: 'id', hidden: true },
{
name: 'first_name',
label: 'First Name',
render: ({ value }: { value: string }) => <span>Sir {value}</span>,
},
{
name: 'last_name',
label: 'Last Name',
},
];
const data = [
{
id: 1,
first_name: 'Frodo',
last_name: 'Baggins',
},
{
id: 2,
first_name: 'Samwise',
last_name: 'Gamgee',
},
];
function App() {
const memoColumns = useMemo(() => columns, []);
const memoData = useMemo(() => data, []);
const { headers, rows, selectRow, selectedRows } = useTable(
memoColumns,
memoData,
{
selectable: true,
}
);
return (
<>
<table>
<thead>
<tr>
<th></th>
{headers.map((header, idx) => (
<th key={idx}>{header.label}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, idx) => (
<tr key={idx}>
<td>
<input
type="checkbox"
onChange={e => {
selectRow(row.id);
}}
/>
</td>
{row.cells.map((cell, idx) => (
<td key={idx}>{cell.render()}</td>
))}
</tr>
))}
</tbody>
</table>
<pre>
<code>{JSON.stringify(selectedRows, null, 2)}</code>
</pre>
</>
);
}
export default App;
Test
npm run test