Download HTML as PDF in React

From Logic Wiki
Jump to: navigation, search


Problems With the Traditional Libraries

react-pdf/renderer is an awesome library and provides lots of customization. but it comes with its own cost. For example

You have to design a separate component for your PDF document

Sometimes the rendering fails if you don’t handle edge-cases properly

You have to style separately and according to their specification. All of these are okay if you want to build a data-heavy and customized PDF. But what if you want something simpler?

Overview

For this, we need two libraries.

  • html2canvas -> will convert our HTML document to image
  • jspdf -> will insert the generated image into a PDF file

Install Dependencies

yarn add jspdf html2canvas

Add The Downloader Function

const downloadPdfDocument = (rootElementId) => {
  const input = document.getElementById(rootElementId);
  html2canvas(input)
    .then((canvas) => {
        const imgData = canvas.toDataURL('image/png');
        const pdf = new jsPDF();
        pdf.addImage(imgData, 'JPEG', 0, 0);
        pdf.save("download.pdf");
    })
}

Complete code

import React from 'react';
import html2canvas from "html2canvas";
import { jsPDF } from "jspdf";

const GenericPdfDownloader = ({rootElementId , downloadFileName}) => {

    const downloadPdfDocument = () => {
        const input = document.getElementById(rootElementId);
        html2canvas(input)
            .then((canvas) => {
                const imgData = canvas.toDataURL('image/png');
                const pdf = new jsPDF();
                pdf.addImage(imgData, 'JPEG', 0, 0);
                pdf.save(`${downloadFileName}.pdf`);
            })
    }

    return <button onClick={downloadPdfDocument}>Download Pdf</button>

}

export default GenericPdfDownloader;

Now you can just place this component anywhere in your project like the following:

import React from'react';
import GenericPdfDownloader from "./views/GenericPdfDownloader";

function App() {
  return (
    <>
        <GenericPdfDownloader 
          downloadFileName="CustomPdf" 
          rootElementId="testId" 
        />
        
        <div id="testId"> 
            This is A Downloadable Component 
        </div>
    </>
  );
}

export default App;