harshvardhan.agr
harshvardhan.agr

Reputation: 175

Make an API call with react-csv

I am trying to add an option to download data as a CSV file inside my component. However, the below code sometimes prints a garbage character  and works other times. I don't understand what I am doing wrong here. I tried to follow the example provided here: https://github.com/react-csv/react-csv#readme

Here is my code

import React, { useState } from "react";
import axios from "axios";

import {
  Card,
  CardHeader,
  CardTitle,
  DropdownItem,
  DropdownMenu,
  DropdownToggle,
  Table,
  UncontrolledDropdown,
  Progress
} from "reactstrap";

import { MoreHorizontal } from "react-feather";
import { CSVLink } from "react-csv";

const Languages = () => {
  const [data, setData] = useState([]);
  return (
  <Card className="flex-fill w-100">
<CardHeader>
      <div className="card-actions float-right">
        <UncontrolledDropdown>
          <DropdownToggle tag="a">
            <MoreHorizontal />
          </DropdownToggle>
          <DropdownMenu right>
            <DropdownItem><CSVLink data={data} filename={'my-file.csv'} asyncOnClick={true}
              onClick={(event, done) => {
                    axios.get("http://localhost:9091/api/returnIndices", {
                      params: {
                        view: 'Series',
                        bucket: '3_7',
                        group: 'Ratings',
                        metric: 'Price Return',
                        download: true
                      }
                    }).then((response) => {
                      const data = response.data.payload;
                      console.log(data);
                      setData(JSON.parse(data));
                      done(false); // REQUIRED to invoke the logic of component
                  });
                }}>Download me</CSVLink></DropdownItem>
        </DropdownMenu>
        </UncontrolledDropdown>
      </div>
      <CardTitle tag="h5" className="mb-0">
        Languages
      </CardTitle>
    </CardHeader>
  </Card>
);
}

export default Languages;

Upvotes: 2

Views: 3071

Answers (1)

harshvardhan.agr
harshvardhan.agr

Reputation: 175

I ended up following the post here https://github.com/react-csv/react-csv/issues/189

Here is what I ended up doing

CsvExport.js

import React, { useState, useEffect, useRef } from 'react';
import { CSVLink } from 'react-csv';
import axios from "axios";
import { config } from '../../../config';

const CsvExport = ({view, bucket, group, metric, startDateMs, endDateMs}) => {
  const [csvData, setCsvData] = useState(false);
  const csvInstance = useRef();
  useEffect(() => {
    if (csvData && csvInstance.current && csvInstance.current.link) {
      setTimeout(() => {
        csvInstance.current.link.click();
        setCsvData(false);
      });
    }
  }, [csvData]);

  return (
    <div type="button" tabIndex="0" role="menuitem" className="dropdown-item">
      <div
        onClick={async () => {
          const newCsvData = await axios.get(config.serviceHost + config.downloadPath, {
            params: {
            view: view,
            bucket: bucket,
            group: group,
            metric: metric,
            startDate: startDateMs,
            endDate: endDateMs,
            download: true
            }
        });
        //   console.log(newCsvData.data.payload);
        const filename = [view, bucket, group, metric, Date.now()].join('_') + '.csv';
          setCsvData({
              data: JSON.parse(newCsvData.data.payload),
              filename: filename
          });
        }}
      >
          Download as CSV
      </div>
      {csvData ?
        <CSVLink
          data={csvData.data}
          filename={csvData.filename}
          ref={csvInstance}
        />
      : undefined}
    </div>

  );
};

export default CsvExport;

Languages.js

<div className="card-actions float-right">
 <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
   <DropdownToggle tag="a">
     <MoreHorizontal />
   </DropdownToggle>
   <DropdownMenu right>
     <CsvExport metric={metric} view={view} bucket={bucket} group={group} startDateMs={this.convertToMs(this.props.startDate)} endDateMs={this.convertToMs(this.props.endDate)}/>
   </DropdownMenu>
 </Dropdown>
</div>

Upvotes: 3

Related Questions