Footer
A footer row renders below the body and above the pagination controls. Use it for totals, averages, counts, or any other summary that should always be visible alongside the data.
There are two ways to declare a footer:
- Column-level
footer— the 80% case. Add afooterfield to anyTableColumn. The footer row appears automatically when at least one visible column has one. -
footerComponentprop — escape hatch. Replace the entire footer row with a custom component when you need multi-row summaries, custom layouts, or aggregates that span columns.
Column-level footers
Pass footer as either a static ReactNode or a function that receives
the filtered+sorted rows and returns a node. Use the function form to compute aggregates —
it sees exactly the rows the user sees in the body, so totals update automatically when you
sort or filter.
Column footers — totals that track filtering
Use the department filter to narrow the rows. The count and salary/bonus totals in the footer update to match what's on screen.
import DataTable, { type TableColumn } from 'react-data-table-component';
const columns: TableColumn<Row>[] = [
{
id: 'name',
name: 'Name',
selector: r => r.name,
sortable: true,
// static label in the footer
footer: rows => `${rows.length} employees`,
},
{
id: 'department',
name: 'Department',
selector: r => r.department,
sortable: true,
},
{
id: 'salary',
name: 'Salary',
selector: r => r.salary,
right: true,
format: r => `$${r.salary.toLocaleString()}`,
// aggregate function — receives the current visible rows
footer: rows => `$${rows.reduce((s, r) => s + r.salary, 0).toLocaleString()}`,
},
{
id: 'bonus',
name: 'Bonus',
selector: r => r.bonus,
right: true,
format: r => `$${r.bonus.toLocaleString()}`,
footer: rows => `$${rows.reduce((s, r) => s + r.bonus, 0).toLocaleString()}`,
},
];
<DataTable columns={columns} data={data} highlightOnHover dense />
Each footer cell inherits its column's right, center,
width, minWidth, and maxWidth — so totals line up
under their column automatically, including after a resize or sort.
Server-side pagination: therowsargument to a footer function contains only the rows currently in the table (the current page). If you need true cross-page totals, usefooterComponentand supply server-computed aggregates yourself.
Custom footer component
Pass footerComponent to replace the footer row entirely. The component receives
{ rows, columns } and can render whatever it likes — multi-stat summaries,
action buttons, contextual copy, anything.
Custom footer component — multi-stat summary bar
The footer bar computes headcount, total salary, average salary, bonus total, and total compensation from the visible rows. Filter by department to see every stat update.
import DataTable, { type FooterComponentProps } from 'react-data-table-component';
function SummaryFooter({ rows }: FooterComponentProps<Row>) {
const totalSalary = rows.reduce((s, r) => s + r.salary, 0);
const totalBonus = rows.reduce((s, r) => s + r.bonus, 0);
const avgSalary = rows.length ? Math.round(totalSalary / rows.length) : 0;
return (
<div style={{
display: 'flex', flexWrap: 'wrap', gap: '16px 32px',
padding: '10px 16px', borderTop: '1px solid #e5e7eb',
backgroundColor: '#f8fafc', fontSize: 13,
}}>
<span><strong>{rows.length}</strong> employees</span>
<span>Salary total: <strong>${totalSalary.toLocaleString()}</strong></span>
<span>Salary avg: <strong>${avgSalary.toLocaleString()}</strong></span>
<span>Bonus total: <strong>${totalBonus.toLocaleString()}</strong></span>
<span>Total comp: <strong>${(totalSalary + totalBonus).toLocaleString()}</strong></span>
</div>
);
}
<DataTable columns={columns} data={data} footerComponent={SummaryFooter} highlightOnHover dense />
When footerComponent is set it takes precedence over any column-level
footer fields.
Controlling footer visibility
The showFooter prop overrides auto-detection:
showFooter— force the footer row on even if no column defines afooter.showFooter={false}— suppress the footer entirely, overriding column footers andfooterComponent. Useful for toggling the summary on and off.- Omitted (default) — auto: render when any visible column has
footerorfooterComponentis provided.
The footer is also automatically hidden during progressPending.
Styling
Use customStyles to override footer appearance:
const customStyles = {
footer: {
style: {
backgroundColor: '#f8fafc',
borderTop: '2px solid #94a3b8',
},
},
footerCells: {
style: {
fontWeight: 700,
color: '#0f172a',
},
},
};
<DataTable columns={columns} data={data} customStyles={customStyles} />
All built-in themes (including their dark modes) set a background.footer value
that gives the footer a distinct surface color matching the header. When building a custom
theme with createTheme, set background.footer to control it:
createTheme('my-theme', {
background: {
default: '#1a1a2e',
header: '#16213e',
footer: '#16213e', // footer matches header
},
}, 'default');
The CSS variable --rdt-color-footer-bg is emitted automatically when
background.footer is set. You can also set it directly in a raw CSS-variable
theme object. It falls back to --rdt-color-header-bg, then
--rdt-color-bg.
Pinned columns
Footer cells in pinned columns stick to the table edge exactly like their body cells — no extra config required. Pinning offsets are computed from the same source as the rest of the table, so they stay aligned after resizing.
Tips
-
Match the footer's display format to the column's
formatfunction. If salaries render as$45,000, format the total the same way. -
Use a static label (
footer: 'Total') on the leftmost column and aggregate functions on numeric columns. -
For multi-row footers, group subtotals, or any layout that doesn't map 1:1 to columns,
reach for
footerComponent— it renders inside arole="rowgroup"container for accessibility and has no constraints on its internal structure.