如何将React JSX原始HTML传递给Api2pdf REST API并优化代码
解决React JSX表格数据传递给Api2pdf的最佳方案
你当前的问题在于Api2pdf接收的是纯HTML字符串,内嵌脚本无法访问React状态,且Api2pdf的渲染环境可能限制脚本执行。以下是两种更简洁可靠的实现方式:
方案一:预渲染数组为HTML片段(适合简单场景)
直接在React环境中将数组映射为HTML字符串,再嵌入到总HTML模板中,无需依赖远程执行脚本:
const fetchReportPdf = async () => { // 预渲染rocktrip数组为<li>标签字符串 const rockTripItems = report.rocktrip.map(item => ` <li>${item.Number_Of_Trips} trips made for Rock Type ${item.RockType}</li> `).join(''); await fetch("https://v2018.api2pdf.com/chrome/html", { method: "post", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: "*Auth key placed here*", }, body: JSON.stringify({ html: ` <html style="color: green" lang="en"> <head> <title>Daily Report for ${newDate}</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" /> </head> <body> <div class="DailyReportTable_Container"> <table class="table table-bordered border-dark table-sm" style="width: 900px" > <tbody> <tr> <th colspan="6" class="text-center"> CIVIL WORKS FOR CONSTRUCTION OF THWAKE DAM EMBARKMENT AND ASSOCIATED WORKS </th> </tr> <tr> <th>INSPECTOR</th> <td colspan="1">${report.User}</td> <th>SECTION:</th> <td colspan="4" style="padding-left: 10px">${report.Section}</td> </tr> <!-- 插入预渲染的数组HTML --> <tr> <td colspan="6"> <ul id="rockTripUL">${rockTripItems}</ul> </td> </tr> </tbody> </table> </div> </body> </html> `, fileName: `${newDate} ${report.Section} ${report.Shift}.pdf`, options: { textAlign: "left", height: "11in", }, }), }) .then((res) => res.json()) .then((res) => { document.getElementById( "Download_Button" ).innerHTML = `<a class="Download_Button" href="${res.pdf}" >Download PDF</a>`; }); };
方案二:用ReactDOMServer渲染完整组件(适合复杂JSX)
如果你的报告是复杂的React组件,直接用ReactDOMServer.renderToString将组件转为HTML字符串,完全复用React的渲染逻辑,无需手动拼接HTML:
- 先导入ReactDOMServer:
import ReactDOMServer from 'react-dom/server';
- 定义你的报告组件:
const ReportComponent = ({ report, newDate }) => ( <html style={{ color: 'green' }} lang="en"> <head> <title>Daily Report for {newDate}</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossOrigin="anonymous" /> </head> <body> <div className="DailyReportTable_Container"> <table className="table table-bordered border-dark table-sm" style={{ width: '900px' }} > <tbody> <tr> <th colSpan="6" className="text-center"> CIVIL WORKS FOR CONSTRUCTION OF THWAKE DAM EMBARKMENT AND ASSOCIATED WORKS </th> </tr> <tr> <th>INSPECTOR</th> <td colSpan="1">{report.User}</td> <th>SECTION:</th> <td colSpan="4" style={{ paddingLeft: '10px' }}>{report.Section}</td> </tr> {/* 直接在组件内渲染数组,和React正常写法一致 */} <tr> <td colSpan="6"> <ul> {report.rocktrip.map(item => ( <li key={item.RockType}> {item.Number_Of_Trips} trips made for Rock Type {item.RockType} </li> ))} </ul> </td> </tr> </tbody> </table> </div> </body> </html> );
- 修改fetch函数,将组件转为HTML字符串传入:
const fetchReportPdf = async () => { // 将React组件转为HTML字符串 const reportHtml = ReactDOMServer.renderToString( <ReportComponent report={report} newDate={newDate} /> ); await fetch("https://v2018.api2pdf.com/chrome/html", { method: "post", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: "*Auth key placed here*", }, body: JSON.stringify({ html: reportHtml, fileName: `${newDate} ${report.Section} ${report.Shift}.pdf`, options: { textAlign: "left", height: "11in", }, }), }) .then((res) => res.json()) .then((res) => { document.getElementById( "Download_Button" ).innerHTML = `<a class="Download_Button" href="${res.pdf}" >Download PDF</a>`; }); };
关键说明
- 内嵌脚本失效的原因:Api2pdf的Chrome渲染服务可能禁用了内嵌脚本执行,且脚本运行在独立环境,无法访问你的React应用状态变量。
- 两种方案的优势:预渲染HTML片段适合简单场景,代码改动小;ReactDOMServer方案适合复杂组件,完全复用React的状态管理和组件逻辑,维护成本更低。
内容的提问来源于stack exchange,提问作者Cosmas Ochieng
相关产品推荐
相关产品推荐

