React中PDF组件渲染完成后实现平滑滚动的问题
解决React-PDF渲染完成后平滑滚动到组件的问题
问题背景
点击按钮触发PDF生成后,需要等待PDFViewer组件完全渲染完成(包含动态生成的PDF内容),再平滑滚动到该组件。当前存在三个核心问题:
- 滚动操作先于组件挂载执行,导致无效果;
- 固定延迟方案无法适配3~300页的可变PDF页数,无法保证滚动时机准确;
- 使用
document.getElementById存在TypeScript类型警告("Object is possibly 'null'")。
技术栈
- React 17.0.2
- react-pdf/renderer 3.0.1
- TypeScript
现有问题代码
import { PDFViewer } from "@react-pdf/renderer"; export const Print: NextPage = () => { const [pdfGenerationEnabled, setPdfGenerationEnabled] = useState<boolean>(false); const generatePDFAndView = async () => { setPdfGenerationEnabled(true); await document.getElementById("generated-pdf-view")?.scrollIntoView({ behavior: "smooth" }); } return ( <DownloadAndPrint> <h2>Generating PDF</h2> <p> Some long text Some long text Some long text . . . </p> <Button className="btn-generate-pdf" onClick={() => { generatePDFAndView() }} > Vygenerovať pdf súbory </Button> {pdfGenerationEnabled ? <> <div id="generated-pdf-view" className="viewer-styled"> <PDFViewer showToolbar={true} style={{ height: "45vh", width: "100%" }}> <ComponentPrint data={data} /> </PDFViewer> </div> </> : "" } </DownloadAndPrint> ); };
优化解决方案
利用React的useRef获取目标元素,结合react-pdf提供的onDocumentLoadSuccess回调(PDF渲染完成时触发)来执行滚动,完美适配不同页数的PDF,同时解决TypeScript类型问题。
修改后完整代码
import { PDFViewer } from "@react-pdf/renderer"; import { useState, useRef } from "react"; export const Print: NextPage = () => { const [pdfGenerationEnabled, setPdfGenerationEnabled] = useState<boolean>(false); // 创建Ref绑定PDF容器,通过泛型指定类型消除TypeScript警告 const pdfViewerRef = useRef<HTMLDivElement>(null); const generatePDFAndView = () => { setPdfGenerationEnabled(true); }; // PDF完全加载渲染完成后触发滚动 const handlePdfRendered = () => { pdfViewerRef.current?.scrollIntoView({ behavior: "smooth" }); }; return ( <DownloadAndPrint> <h2>Generating PDF</h2> <p> Some long text Some long text Some long text . . . </p> <Button className="btn-generate-pdf" onClick={generatePDFAndView} > Vygenerovať pdf súbory </Button> {pdfGenerationEnabled && ( <div ref={pdfViewerRef} className="viewer-styled"> <PDFViewer showToolbar={true} style={{ height: "45vh", width: "100%" }} // 监听PDF加载完成事件,触发滚动 onDocumentLoadSuccess={handlePdfRendered} > <ComponentPrint data={data} /> </PDFViewer> </div> )} </DownloadAndPrint> ); };
方案说明
- useRef替代getElementById:直接将
ref绑定到容器元素,通过TypeScript泛型指定HTMLDivElement类型,彻底消除"Object is possibly 'null'"的类型警告,同时更符合React组件化开发规范。 - onDocumentLoadSuccess回调:
react-pdf官方提供的回调,会在PDF文档所有内容渲染完成后触发,无论页数多少都能准确捕捉到滚动时机,替代不可靠的固定延迟。 - 简化状态逻辑:移除不必要的
async/await,状态更新后组件渲染,待PDF加载完成后自动执行滚动逻辑,流程更清晰可靠。
内容的提问来源于stack exchange,提问作者Elo
相关产品推荐
相关产品推荐

