Export to CSV button in react table
Solution 1
Here is how integration will look like
import React from "react";
import "react-dropdown/style.css";
import "react-table/react-table.css";
import ReactTable from "react-table";
import { CSVLink } from "react-csv";
const columns = [
{
Header: "name",
accessor: "name", // String-based value accessors!
},
{
Header: "age",
accessor: "age",
},
];
class AllPostPage extends React.Component {
constructor(props) {
super(props);
this.download = this.download.bind(this);
this.state = {
tableproperties: {
allData: [
{ name: "ramesh", age: "12" },
{ name: "bill", age: "13" },
{ name: "arun", age: "9" },
{ name: "kathy", age: "21" },
],
},
dataToDownload: [],
};
}
download(event) {
const currentRecords = this.reactTable.getResolvedState().sortedData;
var data_to_download = [];
for (var index = 0; index < currentRecords.length; index++) {
let record_to_download = {};
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
record_to_download[columns[colIndex].Header] =
currentRecords[index][columns[colIndex].accessor];
}
data_to_download.push(record_to_download);
}
this.setState({ dataToDownload: data_to_download }, () => {
// click the CSVLink component to trigger the CSV download
this.csvLink.link.click();
});
}
render() {
return (
<div>
<div>
<button onClick={this.download}>Download</button>
</div>
<div>
<CSVLink
data={this.state.dataToDownload}
filename="data.csv"
className="hidden"
ref={(r) => (this.csvLink = r)}
target="_blank"
/>
</div>
<div>
<ReactTable
ref={(r) => (this.reactTable = r)}
data={this.state.tableproperties.allData}
columns={columns}
filterable
defaultFilterMethod={(filter, row) =>
String(row[filter.id])
.toLowerCase()
.includes(filter.value.toLowerCase())
}
/>
</div>
</div>
);
}
}
export default AllPostPage;
This will work with filters as well.
Solution 2
Take a look at this npm library - https://www.npmjs.com/package/react-csv
For example -
import {CSVLink, CSVDownload} from 'react-csv';
const csvData =[
['firstname', 'lastname', 'email'] ,
['John', 'Doe' , '[email protected]'] ,
['Jane', 'Doe' , '[email protected]']
];
<CSVLink data={csvData} >Download me</CSVLink>
// or
<CSVDownload data={csvData} target="_blank" />
Solution 3
I have it implemented like this in React + Typescript (no dependency):
/**
* @desc get table data as json
* @param data
* @param columns
*/
const getTableDataForExport = (data: any[], columns: any[]) => data?.map((record: any) => columns
.reduce((recordToDownload, column) => (
{ ...recordToDownload, [column.Header]: record[column.accessor] }
), {}));
/**
* @desc make csv from given data
* @param rows
* @param filename
*/
const makeCsv = async (rows: any[], filename: string) => {
const separator: string = ';';
const keys: string[] = Object.keys(rows[0]);
const csvContent = `${keys.join(separator)}\n${
rows.map((row) => keys.map((k) => {
let cell = row[k] === null || row[k] === undefined ? '' : row[k];
cell = cell instanceof Date
? cell.toLocaleString()
: cell.toString().replace(/"/g, '""');
if (cell.search(/("|,|\n)/g) >= 0) {
cell = `"${cell}"`;
}
return cell;
}).join(separator)).join('\n')}`;
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // In case of IE 10+
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
if (link.download !== undefined) {
// Browsers that support HTML5 download attribute
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
};
the table:
<Table data={data} columns={columns} />
and the button:
<button
type="button"
onClick={() => makeCsv(getTableDataForExport(data, columns), `${filename}.csv`)}
>
Download table data CSV
</button>
Solution 4
I thought I'd piggyback on best wishes' extremely valuable answer with a simplified download
implementation.
export = e => {
const currentRecords = this.ReactTable.getResolvedState().sortedData;
this.setState({ dataToDownload: this.dataToDownload(currentRecords, columns) }, () =>
this.csvLink.link.click()
);
}
dataToDownload = (data, columns) =>
data.map(record =>
columns.reduce((recordToDownload, column) => {
recordToDownload[column.Header] = record[column.accessor];
return recordToDownload;
}, {})
);
I used this to allow multiple table exports in one component by adding additional export
functions.
Related videos on Youtube
![Zinngg](https://lh6.googleusercontent.com/-1nHBNM7SX1s/AAAAAAAAAAI/AAAAAAAAAA4/-abVdCqwEHY/photo.jpg?sz=256)
Zinngg
A code blooded magician. Looking for opportunities to learn and grow.
Updated on March 09, 2022Comments
-
Zinngg over 2 years
Looking for a way to add an "Export to CSV" button to a react-table which is an npmjs package (https://www.npmjs.com/package/react-table).
I need to add a custom button for exporting the table data to an excel sheet in the csv or xls format?
-
raj almost 6 yearsHow did you get the data that is present inthe table(like after applying filters). I want to export the data present after applying filters and not the whole original data supplied
-
raj almost 6 yearsWell i got it working finally via setting a ref in the react table insatance and retreiving the current data through this.reactTable.getResolvedState().sortedData
-
xargr over 4 yearsyou can use a simple function to trigger download gist.github.com/xargr/97f160e5ab1bbc513bc7a1acd4ed88e4
-
-
DrMeers almost 6 years...and use
react-table
documented advice onthis.reactTable.getResolvedState()
for getting thedata
prop -
timdewolf over 5 yearsThank you for the example of how to make the link into a button.
-
Himanshu Tanwar over 5 yearsdownload method can be simplified by seperating headers and data. See this link. You can map column header to header ids and pass it to CSVLink component as header prop, and sortedData from table ref as data prop.
-
best wishes about 5 yearsit should, just try once.
-
Finesse almost 5 yearsYou don't need
react-csv
, it only makes things more complicated. Use export-to-csv instead. -
Andre DiCioccio over 4 yearsThank you for fleshing out the example like you have done.
-
Chizl about 3 yearsDoesn't seem to work that way anymore:: "error Arrow function should not return assignment no-return-assign" Happened on "ref={(r) => this.csvLink = r}"
-
best wishes about 3 years
-
Vivek S over 2 yearsThis package does not work on async calls.
-
emmaakachukwu about 2 yearsNice. For anyone wondering what columns should look like, it looks like this: const columns = [ { Header: "first name", accessor: "first_name", }, { Header: "last name", accessor: "last_name", }, ]; The accessor is your value key from your data array.