Exporting a React component to a PDF file on click
Tags: javascript, tutorial, react
Published: 2023-04-18 01:18:33

In this tutorial we’ll covering the process of exporting a React component to a PDF file.

We’ll be using [jsPDF](https://www.npmjs.com/package/jspdf) to generate the PDF which can be installed by running:

`npm install jspdf`

For the purposes of this tutorial we’ll create a simple “shipping label” component which will contain an address and barcode image. Here’s what the basic structure of our `ShippingLabel.js` component will look like:

```javascript
import { jsPDF } from "jspdf";
import Barcode from "./barcode.png";

const ShippingLabel = () => {    
    const createPDF = async () => {
        // TODO
    }; 
    return (<>{/* TODO */}</>);
};

export default ShippingLabel;
```

We’ve used an asynchronous function here so we can use the `await` keyword which will allow us to wait until all the HTML markup has been captured from the component before moving onto the generation of the PDF document.

Now let’s complete the return statement with the HTML markup that we’ll export to the PDF along with a button that’ll generate the PDF when clicked:

```javascript
return (
  <div className="shipping">
    <h1>Download Shipping Label</h1>
    <p>Nihil quam soluta sed enim aut omnis voluptatem reprehenderit.</p>
    <div id="pdf">
        <p>TO: John Citizen</p>
        <p>123 Random Street</p>
        <p>Oak Creek, Colorado (CO), 80467</p>
        <p><img src={Barcode} alt="Barcode" /></p>
    </div>
    <button onClick={createPDF} type="button">Download</button>
  </div>
);
```

Anything outside `<div id="pdf">` will not be exported to the PDF.

We can now complete the `createPDF` function:

```javascript
const createPDF = async () => {
  const pdf = new jsPDF("portrait", "pt", "a4");
  const data = await document.querySelector("#pdf");
  pdf.html(data).then(() => {
    pdf.save("shipping_label.pdf");
  });
};
```
This creates a new `jsPDF` object and set’s the orientation (`portrait`), base unit to be used when coordinates are specified (`pt`), and the document size (`a4`). You can view the full range of options available in the official documentation [here](https://raw.githack.com/MrRio/jsPDF/master/docs/).

If you test what we’ve created so far you’ll notice CSS from external style sheets are not captured in the PDF. If you do want external CSS styles to appear in the PDF you’ll either need to use CSS in JS or another library called `html2canvas` which captures the HTML as image before exporting to PDF.

Let modify our component to capture external CSS by first installing `html2canvas`:

`npm install html2canvas`

And then import into our component:

```javascript
import html2canvas from "html2canvas";
import { jsPDF } from "jspdf";
import Barcode from "./barcode.png";
```

We can now update the `createPDF` function to capture the HTML:

```javascript
const createPDF = async () => {   
  const pdf = new jsPDF("portrait", "pt", "a4"); 
  const data = await html2canvas(document.querySelector("#pdf"));
  const img = data.toDataURL("image/png");  
  const imgProperties = pdf.getImageProperties(img);
  const pdfWidth = pdf.internal.pageSize.getWidth();
  const pdfHeight = (imgProperties.height * pdfWidth) / imgProperties.width;
  pdf.addImage(img, "PNG", 0, 0, pdfWidth, pdfHeight);
  pdf.save("shipping_label.pdf");
};
```

Now when you test the functionality you’ll see any styles from external CSS files are captured in the PDF.

That’s all for this tutorial. You should now have an understanding of how `jsPDF` & `html2canvas` can be used to export a React component to a PDF file. The full source code for the component is available on [GitHub](https://github.com/w3collective/react-component-pdf).