javascript - Loading data asynchronously and downloading CSV data with a click is one step behind the latest retrieved data - St

Using the react-csv package, I am loading data asynchronously and then trying to download the retrieved

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
Add a ment  | 

2 Answers 2

Reset to default 5

Had 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信