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

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>
  );
};

方案说明

  1. useRef替代getElementById:直接将ref绑定到容器元素,通过TypeScript泛型指定HTMLDivElement类型,彻底消除"Object is possibly 'null'"的类型警告,同时更符合React组件化开发规范。
  2. onDocumentLoadSuccess回调:react-pdf官方提供的回调,会在PDF文档所有内容渲染完成后触发,无论页数多少都能准确捕捉到滚动时机,替代不可靠的固定延迟。
  3. 简化状态逻辑:移除不必要的async/await,状态更新后组件渲染,待PDF加载完成后自动执行滚动逻辑,流程更清晰可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:45:35