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 React from 'react';
import { saveAs } from 'file-saver';
import { pdf } from '@react-pdf/renderer';
import PdfDocument from '../PdfDocument';
const generatePdfDocument = async (documentData) => {
const blob = await pdf((
pdfDocumentData={documentData}
/>
)).toBlob();
saveAs(blob, fileName);
};
export default generatePdfDocument;```
@tomasmatulis0 have you seen substantial performance gains from the alternative method you posted with file-saver? In the alternative provided, does this stop the PDF from being generated as the component loads?
@rishipr not quite, I just try to think ahead as it is a good thing to do and having n number of PDFs just ready to be downloaded feels like a waste of resources. Most of the times the user won't even need to download the PDF so it will be just laying there most of the time. I believe it would be an improvement in rare cases when you have more and heavier PDFs on the same page (this would be the way to test it). But again, I believe thinking ahead and saving resources is a good practice.
does the pdf function mean the pdf document is not generated on the fly and only generates/downloads when the generatePdfDocument is called (possibly fixing #420 and #608)?
@idrisadetunmbi not sure about fixing those two problems, but yes using pdf you can generate PDF file blob and download it on generatePdfDocument call. This way we can avoid generating PDF on fly and do it when needed.
Thanks @tomasmatulis0, that makes sense. Solves that problem for me and I think this should be the default.
What is documentData in OP's example code? I am assuming that < PdfDocument /> is:
import React from 'react';
import {
Document,
Page,
Text,
View,
StyleSheet
} from '@react-pdf/renderer';
// Create styles
const styles = StyleSheet.create({
page: {
flexDirection: 'row',
backgroundColor: '#E4E4E4'
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
}
});
// Create Document Component
const PdfDocument = () => (
<Document>
<Page size="A4" style={styles.page}>
<View style={styles.section}>
<Text>Section #1</Text>
</View>
<View style={styles.section}>
<Text>Section #2</Text>
</View>
</Page>
</Document>
);
export default PdfDocument;
@mdodge-ecgrow amm... documentData is just any kind of dynamic data that is passed to the component and add to the pdf (like data got from the API etc.).
That makes sense, thank you.
Nice alternative , thanks tomasmatulis0. Works very well in addition with a spinner state , it's perfect for my letter generation.
const generateLetterPdf = async () => {
setLoadingLetter(true);
const blob = await pdf(
<UserWelcomeLetter customerInfo={customerInfo} />
).toBlob();
setLoadingLetter(false);
saveAs(blob, "Lettre_bienvenue_" + customerInfo.contactName + ".pdf");
};
The OP's work-around with blob and saveAs works for me. In my case, I needed to wire up the PDF to a button, and only render it after the end-user clicked it. Thanks!
I also found that with the download link, it doesn't change when the parameters to the PDF document changes. It seems like the initial document is cached. Therefore I was always getting a blank PDF page without any results, because the first time my page is displayed, the parameters are just an empty array resulting in a PDF document without any data
hmm, i'm trying the code snippet above, but for some reason it trows an err
import React from "react";
import { saveAs } from "file-saver";
import { pdf, Document, Page } from "@react-pdf/renderer";
const generatePDFDocument = async () => {
const blob = await pdf(
<Document>
<Page>// My document data</Page>
</Document>
).toBlob();
console.log(blob);
saveAs(blob, "pageName");
};
export default generatePDFDocument;
Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined
hmm, i'm trying the code snippet above, but for some reason it trows an err
import React from "react"; import { saveAs } from "file-saver"; import { pdf, Document, Page } from "@react-pdf/renderer"; const generatePDFDocument = async () => { const blob = await pdf( <Document> <Page>// My document data</Page> </Document> ).toBlob(); console.log(blob); saveAs(blob, "pageName"); }; export default generatePDFDocument;Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined
Hi, we don't have the full picture there .. if slice is coming from an object defined asynchronously , it needs to be initalized for the first render.. otherwise you might use yourObject?.slice to get undefined returned instead of an error..
@Pat1420 that's very curious because i have no other promises. it's just a click event that's calling generatePDFDocument
<button onClick={() => generatePDFDocument("doc name")}>
download
</button>
there's also this issue
Hi I also have the same issue. It takes 8sec to render a 300 record data. The page will freeze for 8 sec now until the rendering is complete. I can't image how many min it will freeze if the record runs into thousands. If you know of any way to overcome this, please let me know.
Most helpful comment
hmm, i'm trying the code snippet above, but for some reason it trows an err