버튼을 누르면 API 요청을 보내고, 응답 데이터로 CSV 파일을 다운로드 할 수 있게 해주세요.
단, 응답 데이터는 한꺼번에 보낼테니 한 번의 버튼 클릭으로 여러 개의 CSV 파일을 다운로드 받을 수 있어야 해요.
CSVLink에 onClick 이벤트를 붙여서 axios로 응답 데이터를 받아오면 되는, 생각할 것도 없는 기능인 줄 알았는데...
응답이 끝나기 전에 CSVLink를 클릭했다고 인식이 되어서 초기 데이터(빈 배열)로 CSV를 다운로드 시켜주더라 ㅎㅎ;
import React, { useState, useEffect, useRef, memo } from 'react';
import Button from '@material-ui/core/Button';
import { CSVLink } from 'react-csv';
import moment from 'moment';
import axios from 'axios';
const CsvSample= memo((props: any) => {
const csvLink1: any = useRef();
const csvLink2: any = useRef();
const [data1, setData1] = useState<any>([]);
const [data2, setData2] = useState<any>([]);
const clickDownload = async () => {
// params는 알아서 구성
let params = {
param1: "param1"
param2: "param2"
param3: "param3"
};
await axios
.post('url', params)
.then((res: any) => {
parseData(res);
})
.catch((err) => {
console.log(err);
});
};
// axios에 대한 response는 알아서 구성 및 react-csv의 data 형식에 맞게 파싱
const parseData = (input: any) => {
let data1_header = input.data.data1.columns;
let data1_rows = input.data.data1.data;
let _data1 = [data1_header , ...data1_rows ];
let data2_header = input.data.data2.columns;
let data2_rows = input.data.data2.data;
let _data2 = [data2_header , ...data2_rows ];
setData1(_data1);
setData2(_data2);
};
useEffect(() => {
if (data1 && csvLink1 && csvLink1.current && csvLink1.current.link) {
setTimeout(() => {
csvLink1.current.link.click();
setData1([]);
});
}
}, [data1]);
useEffect(() => {
if (data2 && csvLink2 && csvLink2.current && csvLink2.current.link) {
setTimeout(() => {
csvLink2.current.link.click();
setData2([]);
});
}
}, [data2]);
return (
<div>
<Button
variant="outlined"
color="primary"
onClick={() => {clickDownload();}}
size="large"
>
Download
</Button>
{data1.length > 0 ? (
<CSVLink
data={data1}
ref={csvLink1}
filename={`csv-1-${moment().format('YYYYMMDD')}`}
style={{ textDecorationLine: 'none' }}
/>
) : undefined}
{data2.length > 0 ? (
<CSVLink
data={data2}
ref={csvLink2}
filename={`csv-2-${moment().format('YYYYMMDD')}`}
style={{ textDecorationLine: 'none' }}
/>
) : undefined}
</div>
);
});
export default CsvSample;
[참고한 사이트]