Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate file name on current datetime while download in react

I am trying to generate the file name using current date time using below code:

getFileName() {
    let d = new Date();
    let dformat = [this.padLeft(d.getMonth() + 1),
    this.padLeft(d.getDate()),
    d.getFullYear()].join('') +
      '_' +
      [this.padLeft(d.getHours()),
      this.padLeft(d.getMinutes()),
      this.padLeft(d.getSeconds())].join('');

    console.log("getCurrentDate : ", dformat);
    return "GridWidget_" + dformat + ".csv";
  }

    render() {
return(
    <CSVLink data={data} filename={this.getFileName()} className="btn btn-primary" target="_blank">Export To CSV</CSVLink>);
    }

Issue with the above code is like File name is not generated with date time while downloading the file, but the time is taken while the page loads. What I want to do is the filename should generated only when the user clicks the download button.

I know this doesn't make much difference in time but requirement is like should generate it with actual date time. Not able to understand why this is happening.

like image 598
Ravindra Avatar asked Jan 21 '26 13:01

Ravindra


2 Answers

By default you can't do it because filename props is download attribute of <a /> tag which is a built-in HTML. and it generate on render.

<a download="10-36-45.csv" target="_blank" href="">Export To CSV</a>

But there is a hack way you can do by using React Refs to modify attribute of <a> tag.

export default class extends Component {
  $CSVLink = React.createRef();

  getFileName() {
    let d = new Date();
    let dformat = `${d.getHours()}-${d.getMinutes()}-${d.getSeconds()}`;

    console.log("getCurrentDate : ", dformat);
    return "GridWidget_" + dformat + ".csv";
  }

  render() {
    const data = [
      { firstname: "Ahmed", lastname: "Tomi", email: "[email protected]" },
      { firstname: "Raed", lastname: "Labes", email: "[email protected]" },
      { firstname: "Yezzi", lastname: "Min l3b", email: "[email protected]" }
    ];
    return (
      <CSVLink
        onClick={() => {
          this.$CSVLink.current.link.download = this.getFileName();
        }}
        ref={this.$CSVLink}
        data={data}
        filename={this.getFileName()}
        className="btn btn-primary"
        target="_blank"
      >
        Export To CSV
      </CSVLink>
    );
  }
}

I change getFileName method since I don't have information about this.padLeft, getFileName method will return current date so you can see the second changes.

like image 63
Kyaw Kyaw Soe Avatar answered Jan 23 '26 02:01

Kyaw Kyaw Soe


Your getFileName is being called during rendering, you need to call it when the click happens (i.e. CSVLink's onCLick) method. Luckily they provide a way to write async onClick.

First, set a state named filename:

state = {
  filename: ""
}

Now add a callback to CSVLink with asyncOnClick={true}. This function is supposed to be called before any handling logic. See the docs.

In that onClick, set your state and once that is finished call done():

<CSVLink
  data={data}
  asyncOnClick={true}
  filename={this.state.filename}
  onClick={(event, done) => {
    this.setState({
      filename: this.getFileName()
    }, () => {
      done()
    })
  }}
>
  Download me
</CSVLink>;
like image 22
mehamasum Avatar answered Jan 23 '26 03:01

mehamasum