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

react-to-print打印PDF时无法单独调整二维码尺寸问题

问题背景

网站开发中使用react-qr-code生成二维码,使用react-to-print实现二维码导出PDF打印功能。核心需求为在不改变React页面上二维码原有显示尺寸的前提下,单独调整导出PDF文件内的二维码大小。
此前尝试通过state状态修改QRCode组件的size属性,但状态更新会同步修改DOM容器内页面展示的二维码尺寸,无法实现打印尺寸与页面显示尺寸的独立控制,原有问题代码如下:

import QRCode from 'react-qr-code';
import ReactToPrint from 'react-to-print';


  const getPageMargins = () => {
    return `@page { margin: '1000px' '10' '10 '10' !important; }`;
  };

  const onBeforeGetContent = () => {
    setSize(200);
    setIsLoading(true);
    return Promise.resolve();
  };

  const onBeforePrint = () => {
    setSize(100);
    return Promise.resolve();
  };

  const onAfterPrint = () => {
    setSize(100);
    setIsLoading(true);
    return Promise.resolve();
  };

// 渲染部分
     <div ref={QRRef}>
      <QRCode
          value={`{ "_id": "${unit.id}" }`}
          size={size}
      />
      <p className="hide-unit-id">{unit.id}</p>
      </div>
      <ReactToPrint
          pageStyle={getPageMargins}
          onBeforePrint={onBeforePrint}
          onBeforeGetContent={onBeforeGetContent}
          onAfterPrint={onAfterPrint}
          trigger={() => (
              <PrinterFilled />
            )}
          content={() => QRRef.current}>
      </ReactToPrint>
解决方案

最稳定的实现方式是使用打印专属CSS媒体查询,完全不需要动态修改组件state,不会触发页面重渲染,也不会导致页面上的二维码尺寸跳变,天然实现显示尺寸和打印尺寸的隔离。
具体实现步骤:

  • 移除所有动态修改二维码size的state逻辑,删除onBeforeGetContent、onBeforePrint、onAfterPrint中修改size、loading状态的代码,页面上二维码的size属性固定为页面展示需要的尺寸即可,全程不需要改动这个值。
  • 新增打印专属CSS样式,利用@media print媒体查询,仅在触发打印/导出PDF时生效,给二维码设置需要的打印尺寸。注意react-qr-code渲染输出为SVG标签,内联样式优先级高,需要加!important覆盖默认宽高。
  • 修正原有getPageMargins方法的语法错误:原代码margin属性值多了多余的单引号,部分数值缺失单位。

实现代码

首先添加打印样式,可放在全局CSS或组件对应的CSS文件中:

@media print {
  /* 仅打印时生效,完全不影响页面正常显示 */
  .print-qr-container svg {
    width: 200px !important;
    height: 200px !important;
  }
  /* 不需要打印的元素可在此处设置隐藏,比如示例中的unit_id文本如果不需要出现在PDF里可打开下面的注释 */
  /* .hide-unit-id {
    display: none !important;
  } */
}

调整后的组件代码:

import QRCode from 'react-qr-code';
import ReactToPrint from 'react-to-print';
import { PrinterFilled } from '@ant-design/icons';
import { useRef } from 'react';

const QrPrintComponent = ({ unit }) => {
  const QRRef = useRef(null);
  // 固定页面显示的二维码尺寸,不需要用state管理
  const pageDisplayQrSize = 100;

  // 修正后的打印页边距配置,按实际需求调整数值即可
  const getPageMargins = () => {
    return `@page { margin: 10mm !important; }`;
  };

  return (
    <>
      <div ref={QRRef} className="print-qr-container">
        <QRCode
          value={`{ "_id": "${unit.id}" }`}
          size={pageDisplayQrSize}
        />
        <p className="hide-unit-id">{unit.id}</p>
      </div>
      <ReactToPrint
        pageStyle={getPageMargins}
        trigger={() => <PrinterFilled style={{ cursor: 'pointer' }} />}
        content={() => QRRef.current}
      />
    </>
  );
};

export default QrPrintComponent;

方案优势

  • 无页面跳变:全程不修改组件state,不会触发页面重渲染,用户操作时看不到页面上的二维码尺寸变化,体验流畅。
  • 维护简单:打印样式和页面展示样式完全隔离,后续调整尺寸只需要改对应CSS值即可,不需要处理复杂的回调时序问题。
  • 兼容性好:@media print是浏览器原生支持的标准特性,和react-to-print适配无兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:06:20