如何使用@react-pdf/renderer仅在PDF第一页显示图片?
问题:@react-pdf/renderer中仅在第一页显示图片失败
我在React应用中使用@react-pdf/renderer开发PDF生成功能,需要仅在PDF的第一页显示图片及部分文本,但图片完全不显示。我尝试通过给View组件添加render prop,根据页码条件渲染Image组件,但实际没有效果。以下是我的代码:
import { Document, Page, Text, View, StyleSheet, pdf, Image } from '@react-pdf/renderer' import moment from 'moment' import { headerImgPdfQuote } from '../../../Clients/devisTemplate' const styles = StyleSheet.create({ page: { flexDirection: 'column', backgroundColor: '#FFFFFF', padding: '0 40px' }, header: { position: 'absolute', top: 0, left: 0, right: 0 }, headerImage: { width: '100%', height: 'auto' } }) const QuotePDF = () => ( <Document> <Page size="A4" style={styles.page} wrap> <View style={styles.header}> <View render={({ pageNumber }) => ( pageNumber === 1 && ( <Image src={headerImgPdfQuote} style={styles.headerImage} /> ) )} /> <View render={({ pageNumber }) => ( pageNumber === 1 && ( <Text>Reference: {quoteData.ref}</Text> ) )} /> <View render={({ pageNumber }) => ( pageNumber === 1 && ( <Text>{moment(quoteData.createdAt).format('DD/MM/YYYY')}</Text> ) )} /> </View> <Text render={({ pageNumber, totalPages }) => `${pageNumber}/${totalPages}`} fixed /> </Page> </Document> ) const generatePDF = async () => { const blob = await pdf(<QuotePDF />).toBlob() const url = URL.createObjectURL(blob) const link = document.createElement('a') link.href = url link.download = `quote_${moment(quoteData.createdAt).format('DD_MM_YYYY')}.pdf` link.click() }
其中headerImgPdfQuote是经过base64编码的图片(已转为完整的data URI格式)。请问我哪里出错了,如何确保图片仅在第一页显示?
解决方案
错误原因
View组件并不支持通过render prop获取当前页码(pageNumber),只有Page、Text等特定组件支持该特性。你给View添加的render prop不会被触发,导致条件渲染逻辑完全失效,图片自然无法显示。
修正方案
方案1:通过Page组件的render prop实现条件渲染
直接在Page的render回调中获取pageNumber,然后根据页码判断是否渲染头部内容:
import { Document, Page, Text, View, StyleSheet, pdf, Image } from '@react-pdf/renderer' import moment from 'moment' import { headerImgPdfQuote } from '../../../Clients/devisTemplate' const styles = StyleSheet.create({ page: { flexDirection: 'column', backgroundColor: '#FFFFFF', padding: '0 40px', // 给头部留出空间,避免内容被绝对定位的header遮挡 paddingTop: 100 }, header: { position: 'absolute', top: 0, left: 0, right: 0, padding: '0 40px' // 和page的padding保持一致 }, headerImage: { width: '100%', height: 'auto' } }) const QuotePDF = () => ( <Document> <Page size="A4" style={styles.page} wrap render={({ pageNumber, totalPages }) => ( <> <View style={styles.header}> {/* 仅在第一页渲染头部内容 */} {pageNumber === 1 && ( <> <Image src={headerImgPdfQuote} style={styles.headerImage} /> <Text>Reference: {quoteData.ref}</Text> <Text>{moment(quoteData.createdAt).format('DD/MM/YYYY')}</Text> </> )} </View> <Text fixed>{`${pageNumber}/${totalPages}`}</Text> </> )} /> </Document> ) const generatePDF = async () => { const blob = await pdf(<QuotePDF />).toBlob() const url = URL.createObjectURL(blob) const link = document.createElement('a') link.href = url link.download = `quote_${moment(quoteData.createdAt).format('DD_MM_YYYY')}.pdf` link.click() }
方案2:使用usePage钩子封装头部组件
如果需要复用头部逻辑,可以使用@react-pdf/renderer提供的usePage钩子(确保你的版本支持该API):
import { Document, Page, Text, View, StyleSheet, pdf, Image, usePage } from '@react-pdf/renderer' import moment from 'moment' import { headerImgPdfQuote } from '../../../Clients/devisTemplate' const styles = StyleSheet.create({ page: { flexDirection: 'column', backgroundColor: '#FFFFFF', padding: '0 40px', paddingTop: 100 }, header: { position: 'absolute', top: 0, left: 0, right: 0, padding: '0 40px' }, headerImage: { width: '100%', height: 'auto' } }) // 封装仅在第一页显示的头部组件 const FirstPageHeader = () => { const { pageNumber } = usePage() if (pageNumber !== 1) return null return ( <> <Image src={headerImgPdfQuote} style={styles.headerImage} /> <Text>Reference: {quoteData.ref}</Text> <Text>{moment(quoteData.createdAt).format('DD/MM/YYYY')}</Text> </> ) } const QuotePDF = () => ( <Document> <Page size="A4" style={styles.page} wrap> <View style={styles.header}> <FirstPageHeader /> </View> <Text render={({ pageNumber, totalPages }) => `${pageNumber}/${totalPages}`} fixed /> </Page> </Document> ) const generatePDF = async () => { const blob = await pdf(<QuotePDF />).toBlob() const url = URL.createObjectURL(blob) const link = document.createElement('a') link.href = url link.download = `quote_${moment(quoteData.createdAt).format('DD_MM_YYYY')}.pdf` link.click() }
额外注意事项
- 确保
headerImgPdfQuote是完整的data URI格式,例如:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA... - 给
page样式添加paddingTop,避免页面内容被绝对定位的头部遮挡 - 头部的
padding要和页面的padding保持一致,保证内容对齐
内容的提问来源于stack exchange,提问作者Dani
相关产品推荐
相关产品推荐

