React组件设置PDF页数时触发TypeError: 无法操作已分离ArrayBuffer
问题原因及解决方法
错误原因
这个报错是因为React组件重渲染时,你传入react-pdf的原始File对象底层的ArrayBuffer被浏览器垃圾回收机制标记为“分离状态”(detached)。当react-pdf在重渲染过程中尝试再次读取这份数据时,无法访问到有效的内存缓冲区,从而抛出错误。
解决方法
核心思路是将原始File对象转换为稳定的数据格式(比如base64字符串或Blob),避免重渲染时数据被回收。
方法1:将File转换为base64字符串存储
import { useState, useEffect } from 'react'; import { Document, Page } from 'react-pdf'; const PdfViewer = ({ file }) => { const [pdfData, setPdfData] = useState(null); const [numPages, setNumPages] = useState(null); useEffect(() => { if (!file) return; // 用FileReader把File转成base64格式 const reader = new FileReader(); reader.onload = (e) => { setPdfData(e.target.result); }; reader.readAsDataURL(file); }, [file]); if (!pdfData) return <div>加载中...</div>; return ( <div> <Document file={pdfData} onLoadSuccess={({ numPages }) => setNumPages(numPages)}> {numPages && Array.from({ length: numPages }, (_, idx) => ( <Page key={idx} pageNumber={idx + 1} /> ))} </Document> </div> ); }; export default PdfViewer;
方法2:将File转换为Blob对象存储
Blob的生命周期比原始File更稳定,也能避免数据被回收的问题:
import { useState, useEffect } from 'react'; import { Document, Page } from 'react-pdf'; const PdfViewer = ({ file }) => { const [pdfBlob, setPdfBlob] = useState(null); const [numPages, setNumPages] = useState(null); useEffect(() => { if (!file) return; // 基于File创建新的Blob const blob = new Blob([file], { type: file.type }); setPdfBlob(blob); }, [file]); if (!pdfBlob) return <div>加载中...</div>; return ( <div> <Document file={pdfBlob} onLoadSuccess={({ numPages }) => setNumPages(numPages)}> {numPages && Array.from({ length: numPages }, (_, idx) => ( <Page key={idx} pageNumber={idx + 1} /> ))} </Document> </div> ); }; export default PdfViewer;
额外注意点
- 不要直接将原始
File对象作为Document组件的file属性传入,因为File对象的引用在重渲染时可能失效。 - 确保转换后的数据(base64/Blob)通过useState稳定存储,避免每次重渲染都重新转换。
内容的提问来源于stack exchange,提问作者Ubiquitous Ubuntu
相关产品推荐
相关产品推荐

