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

React Native用expo-print时如何将useState状态传入待打印HTML

React Native 中向 expo-print 传入动态状态数据的实现方案

直接拼接动态HTML的标准实现

expo-print 在Android端接收HTML参数打印的逻辑和iOS端完全一致,不需要做特殊适配,核心是用ES6模板字符串构造打印用的HTML,直接把useState管理的状态通过插值语法嵌入到HTML结构里即可,具体写法参考:

import { useState } from 'react';
import { Button, View } from 'react-native';
import * as Print from 'expo-print';

export default function PrintPage() {
  // 示例:useState管理的待打印业务数据
  const [receiptData, setReceiptData] = useState({
    receiptNo: '202405001',
    customer: '李明',
    payAmount: 89,
    goods: [
      { title: '原味奶茶', qty: 1, price: 19 },
      { title: '鸡米花套餐', qty: 2, price: 35 }
    ]
  });

  const triggerPrint = async () => {
    // 用反引号包裹HTML模板,通过${}嵌入状态变量
    const printHtml = `
    <html>
      <head>
        <meta charset="utf-8">
        <style>
          * { margin: 0; padding: 0; box-sizing: border-box; }
          body { padding: 24px; font-size: 14px; line-height: 1.5; }
          .header { text-align: center; font-size: 18px; font-weight: 600; margin-bottom: 20px; }
          .info-line { display: flex; justify-content: space-between; margin: 6px 0; }
          .goods-table { width: 100%; border-collapse: collapse; margin: 16px 0; }
          .goods-table th, .goods-table td { border-bottom: 1px solid #eee; padding: 8px 4px; text-align: left; }
          .total { font-weight: 600; font-size: 16px; margin-top: 12px; }
        </style>
      </head>
      <body>
        <div class="header">消费小票</div>
        <div class="info-line"><span>小票编号</span><span>${receiptData.receiptNo}</span></div>
        <div class="info-line"><span>客户姓名</span><span>${receiptData.customer}</span></div>
        <table class="goods-table">
          <thead>
            <tr><th>商品名称</th><th>数量</th><th>单价</th><th>小计</th></tr>
          </thead>
          <tbody>
            ${receiptData.goods.map(item => `
              <tr>
                <td>${item.title}</td>
                <td>${item.qty}</td>
                <td>¥${item.price}</td>
                <td>¥${item.qty * item.price}</td>
              </tr>
            `).join('')}
          </tbody>
        </table>
        <div class="info-line total"><span>实付金额</span><span>¥${receiptData.payAmount}</span></div>
      </body>
    </html>
    `;

    // 传入构造完成的HTML调用打印
    await Print.printAsync({
      html: printHtml
    });
  };

  return (
    <View style={{padding: 20}}>
      <Button title="发起打印" onPress={triggerPrint} />
    </View>
  );
}

常见踩坑注意点

  • 不要用单引号/双引号定义HTML字符串,必须用反引号(`)包裹,才能支持${}插值语法读取最新的状态值。
  • 嵌入数组、对象这类复杂状态时,不要直接插值,要先把结构遍历转换成HTML字符串再拼接:比如列表数据用map生成对应标签字符串后,必须加.join(''),否则打印内容会出现多余的数组逗号分隔符。
  • Android端打印中文乱码时,必须在HTML的<head>标签内加入<meta charset="utf-8">声明编码。
  • 如果打印内容始终是旧值,检查HTML构造逻辑是否写在了打印事件函数外部,导致闭包捕获了旧的状态值。

替代方案

如果不想手动拼接HTML字符串,可以选择以下方案:

  • 先通过expo-print的printToFileAsync方法生成带数据的PDF文件,再配合expo-sharing调用系统能力完成打印、分享,兼容性比直接调打印更稳定。
  • 替换为react-native-print库,支持直接传入React Native组件节点渲染生成打印内容,不需要手动编写HTML,注意Android端需要额外配置打印相关权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:22:20