使用@react-pdf/renderer在Electron中实现PDF动态数据填充的问题
实现方案
不需要给PDFDoc组件传props的前提下,可通过全局状态共享的方式将API数据注入PDF组件,以下提供两种可直接落地的实现方式:
方案1:轻量状态库实现(推荐)
使用Zustand这类无Provider的状态管理工具,不需要改动组件嵌套结构即可实现跨组件数据共享。
步骤1:创建全局PDF数据存储
新建src/store/pdfStore.ts文件:
import { create } from 'zustand' // 此处替换为你实际从API获取的数据结构 type PDFDataType = { username?: string orderList?: Array<{id: number; amount: number}> } type PDFStore = { pdfData: PDFDataType setPdfData: (data: PDFDataType) => void } export const usePDFStore = create<PDFStore>((set) => ({ pdfData: {}, setPdfData: (data) => set({ pdfData: data }), }))
步骤2:Home组件存入API数据
修改Home.tsx:
import { useEffect } from 'react' import PDFDoc from "/components/PDFDoc"; import { PDFViewer } from '@react-pdf/renderer' import { usePDFStore } from '@/store/pdfStore' export default function Home(){ const setPdfData = usePDFStore(state => state.setPdfData) // 你的API请求逻辑 useEffect(() => { const fetchBusinessData = async () => { const res = await fetch('你的内部API地址') const apiData = await res.json() // 把拉取到的数据存入全局存储 setPdfData(apiData) } fetchBusinessData() }, [setPdfData]) return( <PDFViewer width="100%" height="100%" > <PDFDoc /> </PDFViewer> ) }
步骤3:PDFDoc组件消费数据渲染
修改PDFDoc.tsx:
import { Document, Page, Text, View } from '@react-pdf/renderer' import { usePDFStore } from '@/store/pdfStore' const PDFDoc = () => { const pdfData = usePDFStore(state => state.pdfData) return ( <Document> <Page> <Text>固定文本示例</Text> {/* 渲染动态字段,空值可做兜底展示 */} <Text>用户名称:{pdfData.username ?? '暂无数据'}</Text> {/* 渲染列表类动态数据 */} {pdfData.orderList?.map(order => ( <View key={order.id}> <Text>订单编号:{order.id} | 订单金额:{order.amount}元</Text> </View> ))} <Text render={({pageNumber, totalPages}) => `${pageNumber} / ${totalPages}`} fixed /> </Page> </Document> ) } export default PDFDoc;
方案2:原生React Context实现(无第三方依赖)
如果不想引入额外状态库,可使用React自带的Context实现,步骤如下:
步骤1:创建数据Context
新建src/context/PDFDataContext.tsx:
import { createContext, useContext, useState, ReactNode } from 'react' type PDFDataType = { // 替换为实际API数据结构 username?: string orderList?: Array<{id: number; amount: number}> } const PDFDataContext = createContext<{ pdfData: PDFDataType setPdfData: (data: PDFDataType) => void }>({ pdfData: {}, setPdfData: () => {} }) export const PDFDataProvider = ({ children }: { children: ReactNode }) => { const [pdfData, setPdfData] = useState<PDFDataType>({}) return ( <PDFDataContext.Provider value={{ pdfData, setPdfData }}> {children} </PDFDataContext.Provider> ) } export const usePDFData = () => useContext(PDFDataContext)
步骤2:Home组件包裹Provider并存入数据
修改Home.tsx:
import { useEffect } from 'react' import PDFDoc from "/components/PDFDoc"; import { PDFViewer } from '@react-pdf/renderer' import { PDFDataProvider, usePDFData } from '@/context/PDFDataContext' function HomeInner() { const { setPdfData } = usePDFData() useEffect(() => { const fetchBusinessData = async () => { const res = await fetch('你的内部API地址') const apiData = await res.json() setPdfData(apiData) } fetchBusinessData() }, [setPdfData]) return( <PDFViewer width="100%" height="100%" > <PDFDoc /> </PDFViewer> ) } export default function Home() { return ( <PDFDataProvider> <HomeInner /> </PDFDataProvider> ) }
步骤3:PDFDoc组件消费数据
修改PDFDoc.tsx:
import { Document, Page, Text, View } from '@react-pdf/renderer' import { usePDFData } from '@/context/PDFDataContext' const PDFDoc = () => { const { pdfData } = usePDFData() // 渲染逻辑和方案1完全一致 return ( <Document> <Page> <Text>固定文本示例</Text> <Text>用户名称:{pdfData.username ?? '暂无数据'}</Text> {pdfData.orderList?.map(order => ( <View key={order.id}> <Text>订单编号:{order.id} | 订单金额:{order.amount}元</Text> </View> ))} <Text render={({pageNumber, totalPages}) => `${pageNumber} / ${totalPages}`} fixed /> </Page> </Document> ) } export default PDFDoc;
补充说明
如果你需要用到usePDFAPI生成PDF blob、触发下载等操作,全局数据更新后usePDF返回的实例会自动同步最新内容,无需额外手动触发重渲染。
内容的提问来源于stack exchange,提问作者Jake Starr
相关产品推荐
相关产品推荐

