Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-pdf: use PDFDownloadLink asynchronously without blocking the rest of the application

I'm using PDFDownloadLink from the react-pdf package to generate a PDF on the fly in my application and allow the user to download a report based on data being passed to the component that generates the PDF document. However, there are more than 400 pages that need to be rendered in this PDF, and this operation blocks the main thread for a few seconds. Is there any way to make this operation asynchronous, so the rest of the application will continue to function while the PDF is being generated? Also I would like to be able to cache the results, since the data being passed to the component can come from about 8 different arrays of data, which don't change very much, so switching between these arrays I would rather not to have to render the PDF all over again if the PDF for that given array has already been generated once before... I'm guessing the blob data needs to be stored somewhere, perhaps localStorage?

import { Page, Text, View, Document, StyleSheet, PDFDownloadLink } from '@react-pdf/renderer'
const App = () => {
    const condition = "firstCondition";
    const filteredRowData = rowData.filter(a => a.condition = condition);
    return (
            <PDFDownloadLink
                document={<PDF_REPORT_Document rowData={filteredRowData} />}
                fileName={"PDF_REPORT.pdf"}
                style={{color:'white'}}
                >{({ blob, url, loading, error }) =>
                    loading ? "Report loading..." : "Report ready to download"
                }</PDFDownloadLink>
    );
}

const PDF_REPORT_Document = (props) => {
    const { rowData } = props;
    const styles = StyleSheet.create({
        page: {
          flexDirection: 'column',
          backgroundColor: '#E4E4E4'
        },
        section: {
          margin: 10,
          padding: 10,
          flexGrow: 1
        }
    });

    return(
        <Document>
        {rowData.map((row,index) => 
            <Page size="A4" style={styles.page} key={index}>
                <View style={styles.section}>
                    <Text>Name: {row.FULLNAME}</Text>
                </View>
            </Page>
        )}
        </Document>
    );
}

like image 592
JohnRDOrazio Avatar asked Apr 20 '21 16:04

JohnRDOrazio


Video Answer


1 Answers

I finally found the answer to this in an issue on github which addresses this exact problem:

Is your feature request related to a problem? Please describe. It is an improvement. At the moment, if you use 'PDFDownloadLink' the PDF is being generated as the component loads.

Describe the solution you'd like It is not mandatory, but having multiple heavy PDFs ready to be downloaded wouldn't be the best approach since not every user will need it.

Describe alternatives you've considered I've used pdf() function to generate the blob and file-saver lib to download it:

import { saveAs } from 'file-saver';
import { pdf } from '@react-pdf/renderer';
import PdfDocument from '../PdfDocument';

const generatePdfDocument = async (documentData,fileName) => {
        const blob = await pdf((
            <PdfDocument
                title='My PDF'
                pdfDocumentData={documentData}
            />
        )).toBlob();
        saveAs(blob, fileName);
};

export default generatePdfDocument;
like image 78
JohnRDOrazio Avatar answered Oct 08 '22 13:10

JohnRDOrazio