React-pdf: Can't dynamically render two Text components

Created on 16 Sep 2020  路  9Comments  路  Source: diegomura/react-pdf

I want to put two separate elements in my footer with different styling, both of which need access to the totalPages, however for some reason only the first one is ever displayed.

Can reproduced on the page wrap example (https://react-pdf.org/repl?example=page-wrap) by replacing the single page number element with the following:

      <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
        `a ${pageNumber} / ${totalPages}`
      )} fixed />
      <Text style={[styles.pageNumber, {bottom: 0}]} render={({ pageNumber, totalPages }) => (
        `b ${pageNumber} / ${totalPages}`
      )} fixed />

I would expect to see the 'b' element at the bottom of the screen, with the 'a' above it, but I only see 'a'

Most helpful comment

Alright, I just found in documentation that totalPages is available only in <Text> component.
Here is a little workaround that I found, it's not very readable but it works.

 <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
     <View>
          <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
          <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
     </View>
 )} fixed />

<View> is not really supported (I've experimented stuff like that and inspected the source code) in the render of <Text>. Just use a React.Fragment instead.

<Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
   <>
        <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
        <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
   </>
)} fixed />

All 9 comments

Just wrap them in a <View> component, don't forget to give it fixed inside props if you want those texts to appear in each pdf page. Also consider using debug prop on <View> or <Text>, it gave me a huge help!

@ilyichvismara That doesn't seem to be helping at all for me... Can you give an example of exactly what you mean?
This, for instance, still only renders 'a' and not 'b'

       <View fixed style={styles.pageNumber} >
         <Text debug style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
            `a ${pageNumber} / ${totalPages}`
          )} fixed />
          <Text debug style={[styles.pageNumber, {bottom: 0}]} render={({ pageNumber, totalPages }) => (
            `b ${pageNumber} / ${totalPages}`
          )} fixed />
      </View>

The problem with your code is fixed prop on your <Text> component. Something like that should work.

<View fixed style={{ position:'absolute', bottom:30, textAlign: 'center'}}>
       <Text render={({ pageNumber, totalPages }) => (
        `${pageNumber} / ${totalPages}`
      )}  />
        <Text render={({ pageNumber, totalPages }) => (
        `${pageNumber} / ${totalPages}`
      )}  />
</View>

When you do that, both have totalPages = undefined. I was under the impression that making the Text element itself fixed was required for totalPages to work?

Alright, I just found in documentation that totalPages is available only in <Text> component.
Here is a little workaround that I found, it's not very readable but it works.

 <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
     <View>
          <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
          <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
     </View>
 )} fixed />

Ah, thank you. I didn't think you were allowed to put a View instead of the Text render, but that was because it crashes if you're using styled components for the view/text.

Alright, I just found in documentation that totalPages is available only in <Text> component.
Here is a little workaround that I found, it's not very readable but it works.

 <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
     <View>
          <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
          <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
     </View>
 )} fixed />

<View> is not really supported (I've experimented stuff like that and inspected the source code) in the render of <Text>. Just use a React.Fragment instead.

<Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
   <>
        <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
        <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
   </>
)} fixed />

Alright, I just found in documentation that totalPages is available only in <Text> component.
Here is a little workaround that I found, it's not very readable but it works.

 <Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
     <View>
          <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
          <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
     </View>
 )} fixed />

<View> is not really supported (I've experimented stuff like that and inspected the source code) in the render of <Text>. Just use a React.Fragment instead.

<Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
   <>
        <Text> {`a ${pageNumber} / ${totalPages}\n`}</Text>
        <Text> {`b ${pageNumber} / ${totalPages}`}</Text>
   </>
)} fixed />

Thanks, My issue resolved.

Does anybody know the reason why only one dynamic Element per Page is rendered? I'm trying to make render a table of content and need that functionality therefore. And i would need them to be inline not fixed. Is there a Reason (except that the problem of unknown length, which is not a problem for my case) why only fixed dynamic objects are supported?

Was this page helpful?
0 / 5 - 0 ratings