Export (CSV / JSON)
useTableExport is a headless hook that turns your columns and rows into CSV
or JSON. It can also trigger a browser download or copy to the clipboard. It does not
touch your DataTable; you pass it the same data the table is rendering — or a filtered /
sorted slice if you only want to export the "current view".
New in 8.1.0 — useTableExport ships as part of the library's
headless surface alongside useTableState, useTableData, and friends.
Download and copy
Export the table as CSV or JSON, or copy to clipboard.
import { useState } from 'react';
import DataTable, { useTableExport, type TableColumn } from 'react-data-table-component';
interface Employee { id: number; name: string; department: string; salary: number; }
const columns: TableColumn<Employee>[] = [
{ id: 'name', name: 'Name', selector: r => r.name },
{ id: 'department', name: 'Department', selector: r => r.department },
{ id: 'salary', name: 'Salary', selector: r => r.salary, right: true,
format: r => `$${r.salary.toLocaleString()}` },
];
export default function App() {
const [copied, setCopied] = useState(false);
const { download, copy } = useTableExport({ columns, rows: data, valueSource: 'format' });
async function handleCopy(format: 'csv' | 'json') {
await copy(format);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
return (
<div>
<div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
<button onClick={() => download('employees.csv')}>Download CSV</button>
<button onClick={() => download('employees.json', 'json')}>Download JSON</button>
<button onClick={() => handleCopy('csv')}>{copied ? 'Copied!' : 'Copy CSV'}</button>
</div>
<DataTable columns={columns} data={data} />
</div>
);
} Basic usage
import DataTable, { useTableExport, type TableColumn } from 'react-data-table-component';
type Employee = { id: number; name: string; salary: number };
const columns: TableColumn<Employee>[] = [
{ id: 'id', name: 'ID', selector: r => r.id },
{ id: 'name', name: 'Name', selector: r => r.name },
{ id: 'salary', name: 'Salary', selector: r => r.salary,
format: r => `$${r.salary.toLocaleString()}` },
];
function EmployeesTable({ data }: { data: Employee[] }) {
const { download, copy } = useTableExport({ columns, rows: data });
return (
<>
<div className="flex gap-2">
<button onClick={() => download('employees.csv')}>Download CSV</button>
<button onClick={() => download('employees.json', 'json')}>Download JSON</button>
<button onClick={() => copy('csv')}>Copy CSV</button>
</div>
<DataTable columns={columns} data={data} />
</>
);
} What gets exported
- Columns: all columns are included except those with
omit: true. PasscolumnOrderto restrict and reorder. - Rows: exactly what you pass in. To export the current filtered/sorted view, see the recipe below.
- Values: by default the raw
selectoroutput is stringified. PassvalueSource: 'format'to prefercolumn.formatinstead. - Headers: derived from
column.namewhen it's a string or number; otherwise the columnid. Override per-column withheaderOverrides.
Exporting the current view
DataTable owns sort and pagination state internally, but you can lift them out by using
the headless hooks directly — or just keep a copy of the filtered/sorted rows via the
callbacks. The simplest pattern for "what the user is looking at right now" is to drive
DataTable from the same hooks that feed useTableExport:
import DataTable, {
useTableState,
useTableData,
useColumnFilter,
useTableExport,
} from 'react-data-table-component';
function App() {
// 1. Filters
const { filterValues, handleFilterChange, filteredData } = useColumnFilter(columns);
// 2. Sort + pagination state
const { tableState, handleSort, /* ... */ } = useTableState({ /* ... */ });
// 3. Apply sort + pagination
const { sortedData, tableRows } = useTableData({
data: filteredData(rawData),
columns,
selectedColumn: tableState.selectedColumn,
sortDirection: tableState.sortDirection,
currentPage: tableState.currentPage,
rowsPerPage: tableState.rowsPerPage,
pagination: true,
});
// 4. Export the filtered + sorted full result (not just the current page).
// Swap `sortedData` for `tableRows` to export just the current page.
const { download } = useTableExport({ columns, rows: sortedData });
return (
<>
<button onClick={() => download('view.csv')}>Export filtered view</button>
<DataTable columns={columns} data={rawData} pagination />
</>
);
}
For server-side data, just pass whatever rows the server returned for your current
filters — useTableExport doesn't care where the rows came from.
Customizing column output
Reorder and restrict columns
useTableExport({
columns,
rows: data,
columnOrder: ['name', 'salary', 'id'], // export these three, in this order
}); Override header labels
Useful when column.name is a React node (e.g. an icon + text), or when the
export needs a different label than the UI shows:
useTableExport({
columns,
rows: data,
headerOverrides: {
name: 'Full Name',
salary: 'Annual Salary (USD)',
},
}); Export formatted values
By default, exports use raw selector values so a CSV "salary" column contains
80000 rather than $80,000. To export what the user sees, opt
into valueSource: 'format':
useTableExport({ columns, rows: data, valueSource: 'format' }); Clipboard support
copy() uses the navigator.clipboard API and returns a Promise
that resolves once the write completes. It throws if the API is not available (older
browsers, insecure contexts).
async function handleCopy() {
try {
await copy('csv'); // or 'json'
toast.success('Copied to clipboard');
} catch (err) {
toast.error('Clipboard not available');
}
} SSR safety
Both download and copy guard against document /
navigator being undefined, so calling them during server rendering is a
no-op rather than a crash. The hook itself does no browser-only work at render time.
CSV escaping
Values containing commas, quotes, or newlines are wrapped in double quotes and any
interior quotes are doubled — the standard RFC 4180 rule. Booleans and numbers are
coerced with String(). null and undefined become
empty cells. Anything more complex (objects, React nodes) is run through
JSON.stringify as a safety net.
API
| Option | Type | Default | Description |
|---|---|---|---|
columns | TableColumn<T>[] | required | Same columns array you pass to DataTable. Columns with omit: true are skipped. |
rows | T[] | required | Rows to export. |
valueSource | 'selector' | 'format' | 'selector' | Use raw selector values or run column.format first. |
headerOverrides | Record<string|number, string> | — | Replace header label per column id. |
columnOrder | (string|number)[] | — | Restrict and reorder columns by id. |
Returns
| Property | Type | Description |
|---|---|---|
toCSV | () => string | Build a CSV string (no download). |
toJSON | () => string | Build a pretty-printed JSON array string. |
download | (filename, format?) => void | Trigger a browser download. format defaults to 'csv'. |
copy | (format?) => Promise<void> | Copy to clipboard. Rejects when the clipboard API is unavailable. |