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

react-pdf避免重复请求PDF文件问题求助

解决react-pdf首次加载后重复发起网络请求的问题

你的问题核心在于:组件重渲染时file对象的引用发生变化,导致Document组件重新触发PDF加载请求;同时onLoadSuccess函数每次渲染都会重新创建,也可能引发不必要的组件更新。以下是有效解决方案:

关键修复点

  1. 正确缓存file对象:用useMemo缓存时,直接依赖url(而非每次渲染都会新建的对象),确保只有当url变化时才重新生成file。
  2. 稳定onLoadSuccess函数引用:用useCallback包裹该函数,避免每次渲染创建新函数,减少Document组件的不必要更新。

完整修正代码

import React, { FC, useMemo, useState, useCallback } from 'react'
import { Document, Page, pdfjs } from 'react-pdf'

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`

export interface PDFProps {
  url: string
  width?: number
  onLoadError?: Document['props']['onLoadError']
  onSuccess?: () => void
}

export const PDF: FC<PDFProps> = ({ url, onSuccess, onLoadError }) => {
  const [pageNumbers, setPageNumbers] = useState<number[]>([])

  // 仅当url变化时,才重新创建file对象
  const file = useMemo(() => ({ url, withCredentials: true }), [url])

  // 用useCallback稳定函数引用,避免触发Document重渲染
  const onLoadSuccess = useCallback<Document['props']['onLoadSuccess']>(({ numPages }) => {
    if (numPages !== pageNumbers.length) {
      const pagesIndex = [...Array(numPages).keys()].map(pageIndex => pageIndex + 1)
      setPageNumbers(pagesIndex)
      onSuccess?.()
    }
  }, [pageNumbers.length, onSuccess])

  return (
    <Document
      options={{
        standardFontDataUrl: `https://unpkg.com/pdfjs-dist@${pdfjs.version}/standard_fonts`,
      }}
      file={file}
      onLoadSuccess={onLoadSuccess}
      onLoadError={onLoadError}
    >
      {pageNumbers.map(pageNumber => (
        <div key={pageNumber}>
          <Page pageNumber={pageNumber} />
        </div>
      ))}
    </Document>
  )
}

修复原理

  • useMemo依赖url而非整个对象,确保组件重渲染时file的引用保持稳定,Document不会因为file变化重新发起请求。
  • useCallback让onLoadSuccess函数仅在pageNumbers.length或onSuccess变化时才重新创建,避免Document因函数引用变化触发不必要的更新。
  • 用可选链onSuccess?.()简化了回调触发的逻辑。

内容的提问来源于stack exchange,提问作者bssyy78

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:55:17