React-pdf: Can I Reuse an Existing React Component inside of react-pdf Document component?

Created on 21 Feb 2019  路  4Comments  路  Source: diegomura/react-pdf

What I'm trying to achieve

Convert an existing React component (and all of it's styles) into a PDF document. For the purposes of this question, let's call this already existing component <ProfilePage />. This component is made up of your normal React element primitives: <div>, <p> etc.

Solutions I've tried

Putting <ProfilePage /> as a child of <Document> and <Page>

<Document>
  <Page>
    <ProfilePage />
  </Page>
</Document>

Additional information

This is my first time getting into creating PDF printable pages on the web so I am a real newbie when it comes to this. The react-pdf documentation isn't really clear in answering certain questions for me. The biggest one being, when it comes to this idea of creating PDFs, do we have to essentially create two versions of our component -- one using normal React primitives and the other using react-pdf primitives?

Because in my mind, I already have a designed view in my web app. All I want to do is print out that component as is. I'm hoping I can reuse said component inside of react-pdf but I have a sinking feeling that I'm thinking about this all wrong and I may have to re-implement my view using the primitives of this library.

Also, how would I go about adding a download PDF button experience using react-pdf? My thinking was if I have a download PDF button on my page, all I would have to do is trigger ReactPDF.render(<DocumentWrappedProfilePage />, '${__dirname}/example.pdf'); in the button's onClick handler.

Is this thinking correct?

Most helpful comment

That would be great!

All 4 comments

Hi @thedanchez !
Thanks for trying react-pdf.
Let me break your issue in smaller parts


The react-pdf documentation isn't really clear in answering certain questions for me.

Sorry that you felt that way. Maybe we can create a FAQ section on the docs for common questions, but it's hard to identify what questions should be there.


When it comes to this idea of creating PDFs, do we have to essentially create two versions of our component

Yes. Trying to render dom elements inside the PDF will throw an error. I know it may sound unfortunate, but this is how most renderers work (you cannot render a React Native component in the web either). In addition, even though react-pdf tries to stick to the CSS properties, there are certain things that you have to define differently (ex. all nodes in react-pdf have display: flex). This is because how Yoga works. What this means is that there's no guarantee that reusing styles will produce the same output. Also, react-pdf does not support all CSS properties (_yet!_)

However, these are all React elements. You can create an easy script that transforms DOM elements into react-pdf elements:

Input

{
  type: 'div',
  props: {
    style: { backgroundColor: 'red' },
    children: [
      {
        type: 'p',
        props: {
          children: 'Lorem Ipsum'
        }
      }
    ]
  }

Output

{
  type: 'VIEW',
  props: {
    style: { backgroundColor: 'red' },
    children: [
      {
        type: 'TEXT',
        props: {
          children: 'Lorem Ipsum'
        }
      }
    ]
  }

But as I said, you may need to edit styles for the PDF.
I can come up with that script, but you should use it under your own risk.

Another alternative would be for all your _reusable_ components to have a static value called PDF that includes that same component but to be rendered by react-pdf. However, this means that you will have to write your components "twice" (even though I don't consider it duplicating code).


Also, how would I go about adding a download PDF button experience using react-pdf?

If you read the docs, ReactPDF.render is a Node only API. You have all the details of how to achieve what you want here

Hope this helped!
If I write that script I'll let you know here

We needed to avoid rewriting loads of React components designed to render HTML-style components to the DOM, so we are taking normal JSX, substituting React.createElement for a custom function using a Babel pragma and substituting HTML component names for react-pdf components designed to to the same thing in PDF.

If you would be interested @diegomura, we could contribute the custom components we鈥檝e written to a branch for the community to improve?

This would also address #487.

That would be great!

@diegomura Thank you for answering my question on this -- it was super helpful and informative for me!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

serkyen picture serkyen  路  4Comments

emt1803 picture emt1803  路  3Comments

mdodge-ecgrow picture mdodge-ecgrow  路  3Comments

foureyedraven picture foureyedraven  路  3Comments

brandly picture brandly  路  3Comments