Using the react-csv
package, I am loading data asynchronously and then trying to download the retrieved data from the server with one click. The problem I am currently facing is that the click is a step behind the current state. When the ponent first renders it downloads an empty CSV file and on the second click it downloads the data from the previous fetch, not the current/latest fetch. That is the same situation that is described here, but the solution mentioned there didn't work in my case.
Here is the code I'm working on:
const [newData, setNewData] = useState([]);
const csvLink = React.createRef();
const csvExport = (
<div>
<Button className="pull-right title-button" onClick={getData}>
CSV Export
</Button>
<CSVLink data={newData} headers={headers} target="_blank" ref={csvLink}></CSVLink>
</div>
);
const getData = async () => {
await getRetailLinkOutes(auth, startDate, endDate, 0, 0, filters, sort, sortDirection, false).then((response) => {
setNewData(response.records);
csvLink.current.link.click();
});
};
Using the react-csv
package, I am loading data asynchronously and then trying to download the retrieved data from the server with one click. The problem I am currently facing is that the click is a step behind the current state. When the ponent first renders it downloads an empty CSV file and on the second click it downloads the data from the previous fetch, not the current/latest fetch. That is the same situation that is described here, but the solution mentioned there didn't work in my case.
Here is the code I'm working on:
const [newData, setNewData] = useState([]);
const csvLink = React.createRef();
const csvExport = (
<div>
<Button className="pull-right title-button" onClick={getData}>
CSV Export
</Button>
<CSVLink data={newData} headers={headers} target="_blank" ref={csvLink}></CSVLink>
</div>
);
const getData = async () => {
await getRetailLinkOutes(auth, startDate, endDate, 0, 0, filters, sort, sortDirection, false).then((response) => {
setNewData(response.records);
csvLink.current.link.click();
});
};
Share
Improve this question
edited Nov 23, 2024 at 8:48
Sadra Saderi
3944 silver badges12 bronze badges
asked Nov 13, 2020 at 8:21
Ferhi MalekFerhi Malek
5147 silver badges15 bronze badges
2
- Were you able to resolve this? Having the same issue, where the data is one step behind the current state and it takes two clicks to download the correct data – N.A Commented Feb 14, 2021 at 22:41
- 2 Update: I resolved my issue by putting the csvLink.current.link.click(); inside a useEffect hook that checks if the data is not null, and also wrapping it in a setTimeout. Referenced here: github./react-csv/react-csv/issues/72 – N.A Commented Feb 14, 2021 at 23:47
2 Answers
Reset to default 5Had the same issue, resolved it by not using <CSVLink asyncOnClick>
(which was a nightmare with Typescript and flat out didn't work unless the user clicked the button twice or unless data was prefetched)
To handle fetching asynchronous data, you can use a normal button to initiate the async fetch and a conditionally rendered button that downloads the CSV
const [initiateDownload, setInitiateDownload] = useState(false)
const [csvRows, setCsvRows] = useState([])
const fetchCsvData = async () => {
const response = await fetchData()
setCsvRows(response.data)
}
useEffect(() => {
if (csvRows.length) {
setInitiateDownload(true)
}
}, [csvRows])
useEffect(() => {
// Enables user to download data more than once
if (initiateDownload) {
setInitiateDownload(false)
}
}, [initiateDownload])
return (
<button onClick={fetchCsvData}>Export CSV</button>
{initiateDownload && (
<CSVDownload
data={csvRows}
headers={csvHeaders}
target="_blank"
/>
)}
)
Elaborating more on what N.A mentioned in the ments:
const [data, setData] = useState([])
const [headers, setHeaders] = useState([])
const excelRef = useRef()
The function to fecth data :
function requestAllHistory () {
console.log('requesting excel history')
requestAllHistoryForExcel(function (response, error) {
// data and headers fetched
setData(data)
setHeaders(headers)
})
}
Inside useEffect
useEffect(() => {
if (headers.length > 0) {
console.log('ExportExcel useEffect', headers)
excelRef.current.link.click()
}
}, [headers])
The CSVLink should not be displayed on the UI (display:'none')
return (
<span>
<button
type='button'
className='btn btn-lg btn-dark'
onClick={() => requestAllHistory()}
>
<span> Export to Excel </span>
<span className='download'></span>
</button>
<CSVLink
data={data}
headers={headers}
filename={filename}
ref={excelRef}
className='hiddenExcel'
target='_blank'
></CSVLink>
</span>
)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744047411a4549437.html
评论列表(0条)