You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:24:03