react-pdf icon indicating copy to clipboard operation
react-pdf copied to clipboard

Support hooks in dynamic nodes

Open robinweser opened this issue 1 year ago • 2 comments

Hey there!

I'm working on a higher-level system on top of this library to bring document-wide theming, indexing (e.g. to generate table of contents) and much more. So far, everything works perfect in basic documents, but I run into issues when using the render prop approach for dynamic nodes. I get the infamous Invalid hook call. and I guess it is due to the library not supporting hooks inside of render props due to directly calling the render function or something. I find it a bit hard to navigate the source code to trim down the actual lines where this is resolved. I need hooks for config and theme context that my base level components use.

Consider this minimal reproduction:

import { createContext, useContext } from "react"
import { Page, Document, View, Text } from "@react-pdf/renderer"

const ThemeContext = createContext({})

function ThemedText({ children }) {
  const theme = useContext(ThemeContext)

  return <Text style={{ color: theme.colors.primary }}>{children}</Text>
}

function MyDocument() {
  return (
    <ThemeContext.Provider value={{ colors: { primary: "red" } }}>
      <Document>
        <Page>
          <ThemedText>Works here</ThemedText>
          <View
            render={({ pageNumber }) => (
              <ThemedText>Doesn't work here</ThemedText>
            )}
          />
        </Page>
      </Document>
    </ThemeContext.Provider>
  )
}

For theme and config I could also use a singleton for now, but I also need context for inheritance in some components such as my custom Text. I get that most hooks such as useState and useEffect don't make sense in a static document, but context would actually be super useful due to sub-tree support e.g. having different themes and configs per subpage or something. I'm more than happy to help if you guide me to the right direction! Would really add so much value for my library. Oh, and I also tried to use Context.Consumer instead of hooks just like we did before hooks shipped, but it also doesn't work properly. I think the issue lies somewhere in createInstances, but I wasn't able to fix it myself for now.

robinweser avatar Sep 09 '23 19:09 robinweser