Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow <Document> to be wrapped by context provider Elements in node #1371

Closed
nagiek opened this issue Jun 14, 2021 · 7 comments
Closed

Allow <Document> to be wrapped by context provider Elements in node #1371

nagiek opened this issue Jun 14, 2021 · 7 comments

Comments

@nagiek
Copy link

nagiek commented Jun 14, 2021

Is your feature request related to a problem? Please describe.
I want to use the renderToFile method in node to generate a PDF. I also want to use the react-intl library to provide messages. I therefore want to consume context from within the from the parent .

Describe the solution you'd like
I would like for react-pdf to drill-down within the tree that I provide for the and set it as the root node. It should no longer assume that it is the first child. This should only be used within the node context, there are no user interactions and therefore no reason why doing this would trigger re-renders or any other “bad” behaviour. This functionality would only be used for high-level context providers like . It would not be used to create a multi-node tree higher than the .

Describe alternatives you've considered
I haven’t seen anyone try to implement an intl library with react-pdf, so not sure it has been done.

Additional context
I am using a build process which will wrap the with and then try to render a file.

@nagiek nagiek changed the title Allow <Document> to be wrapped by context provider Elements. Allow <Document> to be wrapped by context provider Elements in node Jun 14, 2021
@nagiek
Copy link
Author

nagiek commented Jun 14, 2021

Note: I’ve seen a similar request for this in this issue. However, this is on the web/dom side, whereas my use case is on the node/server side.
#522

@diegomura
Copy link
Owner

diegomura commented Jun 15, 2021

This is an issue on the React side unfortunately. There's an open ticket for awhile now facebook/react#17275. I'll leave #522 to register this issue. Node or web in this case I don't think it changes, since it's on the isomorphic part of React

@nagiek
Copy link
Author

nagiek commented Jun 15, 2021

Thank you for the quick response! I’ve tried to dive into react-reconciler but it’s quite advanced.

If it helps, I’m not trying to share contexts,
I am trying to render a wrapped <Document>. It seems to me that react-pdf expects <Page> to be an immediate child of the root <Document>, and complains if it is not the case. Maybe we could add something to find <Document> within the tree, and then use it as the document node, rather than assume the document will definitely be at the root node.

const findDocumentNode = doc => {
  if (!doc) return null;
  if (React.isValidElement(doc) && doc instanceof Document) return doc;
  const child = React.Children.only(doc.props.children);
  return findDocumentNode(child);
}

I’m just not entirely sure where this should go.

@kidroca
Copy link
Contributor

kidroca commented Jun 15, 2021

I'm successfully providing a theme with color and theming functions through context by wraping the Page with a ThemeProvider like so

  <Document author="Diasyst">
    <ThemeProvider>
      <Page size="A2" orientation="portrait" style={{ paddingBottom: FOOTER_HEIGHT }}>
        {
          patient?.reportData && (
            <PdfBillingReport
              patient={patient}
              data={patient.reportData}
              reportedOn={DateTime.now().toISODate()}
            />
          )
        }
      </Page>
    </ThemeProvider>
  </Document>

And here's the provide

const ThemeProvider = ({ children }) => {
  const theme = useColorScheme();
  return (
    <StylesProvider injectFirst>
      <MuiThemeProvider theme={theme}>
        <EmotionCacheProvider value={emotionCache}>
          <EmotionThemeProvider theme={theme}>
            {children}
          </EmotionThemeProvider>
        </EmotionCacheProvider>
      </MuiThemeProvider>
    </StylesProvider>
  );
};

I'm successfully using useTheme in my components and pass some stuff like colors to the Views and Text that I use

Why won't that work for your case, perhaps the Provider is not returning children directly but adds some element - div?

@nagiek
Copy link
Author

nagiek commented Jun 16, 2021

Actually that could work! I assumed <Page> had to be a direct descendant of <Document>. Will test it out and report back. Thanks!

@nagiek
Copy link
Author

nagiek commented Jun 16, 2021

Worked! Successfully put my Providers in my Document before my Pages. Thank you so much for your help!

@NickyStraub
Copy link

Hey guys, sorry to revive a dead thread but I'm just a bit curious about this. @kidroca's solution works for my use case so no problems there, but just for testing sake, I tried moving my Context.Provider outside of the PDFViewer that I am rendering and the context no longer updates for components within my Document (which is wrapped by the PDFViewer).

Just wondering if anyone knows why that would be the case? Is it somehow related to the fact that PDFViewer extends React.Component<...> and not React.Component<React.PropsWithChildren<...>>?

Apologies if this is an obvious question 😄

This works (meaning components inside can access the stored context):

<>
  <PDFViewer showToolbar={false}>
      <PDFDataContext.Provider value={data}>
          <MyPDF/>
      </PDFDataContext.Provider>
  </PDFViewer>
</>

This does not:

<>
  <PDFDataContext.Provider value={data}>
      <PDFViewer showToolbar={false}>
          <MyPDF/>
      </PDFViewer>
  </PDFDataContext.Provider>
</>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants