React-pdf: Prevent BlobProvider from being reactive

Created on 26 Nov 2018  路  4Comments  路  Source: diegomura/react-pdf

OS:
macOs Mojave 10.14

React-pdf version:
"@react-pdf/renderer": "^1.0.0-alpha.19",

Description:
Currently I am using BlobProvider in this way...

{!this.props.loading ?
    <div style={{float:'left'}}>
      {this.props.pdfPrintable ?
         <BlobProvider document={this.generateOrderPDF(this.props.form.getFieldsValue())}>
         {({ url }) => (
            <Button href={url} target="_blank" type="primary" style={{marginRight:'5px'}} className="download-pdf-btn ant-btn btn-secondary ant-btn-primary" loading={false}>Print</Button>
         )}
         </BlobProvider>
      :
         <Button href="#" target="_blank" type="primary" style={{marginRight:'5px'}} className="download-pdf-btn ant-btn btn-secondary ant-btn-primary" loading={true}>Print</Button>
      }
   </div>
: null}

<Button loading={Session.get('processing')} className="btn-secondary" type="primary" htmlType="submit">Save</Button>

Basically, each time I enter any character in any field, or make any selection from a dropdown, or make a radio selection, the PDF is updating. After a lot of trial and error where the PDF was not rendering changes made in fields etc. this was the only way I was able to get everything to work.

After running into countless issues/errors where the PDF would try to update itself while it was already rendered, I had to implement the pdfPrintable state which basically, upon each change in the form, will disable the button, re-render the PDF and enable the button again.

However, this is really not ideal at all, as the whole form/page becomes very laggy because it has to update after every change. It was ok at first but my PDF has become quite complex and it is no longer a viable solution.

What I want is to only render the form when I click the 'Print' button.
Is this possible?

Most helpful comment

Thanks @diegomura

I've figured it out...

printPDF = () => {
  var obj = pdf(<BlankPDF />).toBlob();
  obj.then(function(blob) {
    var url = URL.createObjectURL(blob);
    window.open(url, '_blank');
  });
}

All 4 comments

BlobProvider will always reflects the content of the document prop. So if this changes, the PDF will re-render to be sync with it. If you want to behave differently you can use the render API directly instead of using BlobProvider at all:

import { pdf } from '@react-pdf/renderer'; 

pdf(<MyDocument />).toBlob();

@diegomura This sounds good, but how can I mimic the current setup that I have using this? How can I click the button and render the PDF in a new tab?

I have tried this but it does nothing...

const BlankPDF = () => (
  <Document>
    <Page style={styles.page} wrap debug>
      <View>
        <Text>Testing</Text>
      </View>
    </Page>
  </Document>
)
printPDF = () => {
    pdf(<BlankPDF />).toBlob();
 }

<Button onClick={this.printPDF} target="_blank">Print</Button>

Are there any docs about the API?

After calling pdf(<Doc/>).toBlob() you obviously get the document blob. So what you want is to open a blob in a different tab. I鈥檓 don鈥檛 remember by heart how you can to this but im pretty sure you can find a solution somewhere on the internet 馃槈

Thanks @diegomura

I've figured it out...

printPDF = () => {
  var obj = pdf(<BlankPDF />).toBlob();
  obj.then(function(blob) {
    var url = URL.createObjectURL(blob);
    window.open(url, '_blank');
  });
}
Was this page helpful?
0 / 5 - 0 ratings