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".
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 contains80000 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 throughJSON.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. |
Need the reverse direction? See the CSV import recipe.