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

React-pdf在Syncfusion Tab中已加载却仍显示加载状态的问题

问题描述

我使用Syncfusion Tab组件实现标签页切换展示多种类型文件,其中PDF文件通过react-pdf组件渲染。通过useQuery从服务器数据库获取文件(可在控制台打印文件内容),但切换标签页时会重新触发查询并清空文件,且Tab组件内的react-pdf始终卡在加载状态。单独使用react-pdf搭配按钮触发useQuery可正常显示PDF,集成到Tab组件中则失效。

相关代码

useQuery 代码

const { status, data, error, isFetching, refetch } = useQuery(['facture', id], async () => {
     const data = await getUniqueCassandraFile(id)
     setFile(data.rows[0].file)
     return data.rows[0].file
}, {
     enabled: false,
     refetchOnWindowFocus: false
})

renderPdf 函数

export const renderPdf = (id, file) => {
    if(!file){
        return waiting(id)
    }
    return (
        <div key={id} className='file_container'>
            <Document file={`data:application/pdf;base64,${file}`} style={{height:50+'vh'}}>
                <Page size="A4" pageNumber={1} className="pdfFacture">
                </Page>
            </Document>
        </div>
    )
}

TabComponent 代码

<div className="control-section tab-control-section">
   {chosenItem === -1 ? emptyDiv : 
   <TabComponent overflowMode="Scrollable" id="defaultTab" selecting={selecting} 
   selectedItem={chosenItem}>
      <TabItemsDirective>
      {
         header.map((item, index) => {
            return <TabItemDirective presentation={true} key={index} header={item} 
               content={{
                  template: tabContent, 
                  data: {content: content[index], type: item.type, id: item.id}}}/>
               })
            }
            </TabItemsDirective>
         </TabComponent>
      }
 </div>

TabContent 模板

const tabContent = (data) => {
   return <div dangerouslySetInnerHTML={{__html: ReactDOMServer.renderToStaticMarkup(
             isFetching ? emptyDiv :
             switchRender(data.id, data.type, file))}}>
   </div>;
};

问题原因及解决方案

核心原因

  1. 静态HTML渲染破坏动态组件逻辑:react-pdf的Document和Page依赖React生命周期和DOM动态更新,但renderToStaticMarkup将组件转为静态HTML字符串,丢失了动态交互能力,导致PDF无法完成加载。
  2. 状态不同步与组件重置:切换标签页时,Tab组件可能卸载/重挂载内容,加上useQuery的触发逻辑,导致file状态被清空,而静态HTML无法响应状态变化。

修复步骤

1. 移除静态HTML转换逻辑

直接在Tab内容模板返回React组件,让react-pdf参与正常渲染流程:

const tabContent = (data) => {
  return isFetching ? emptyDiv : switchRender(data.id, data.type, file);
};

2. 优化useQuery状态管理

去掉额外的setFile,直接使用useQuery返回的data,避免状态不同步:

const { status, data, error, isFetching, refetch } = useQuery(['facture', id], async () => {
  const res = await getUniqueCassandraFile(id);
  return res.rows[0].file;
}, {
  enabled: false,
  refetchOnWindowFocus: false
});

// 渲染时直接使用data:renderPdf(id, data)

3. 控制Tab内容的查询触发

在selecting回调中仅触发当前激活标签页的refetch,避免切换时无意义的状态重置:

const selecting = (args) => {
  const targetTabId = header[args.selectedIndex].id;
  // 调用对应id的refetch
  refetch({ id: targetTabId });
};

4. 确保react-pdf响应文件更新

修改renderPdf的key,让文件变化时组件重新挂载,触发PDF重新加载:

export const renderPdf = (id, file) => {
    if(!file){
        return waiting(id)
    }
    // 用文件内容片段作为key的一部分,确保文件更新时组件重建
    return (
        <div key={`pdf-${id}-${file.slice(0, 10)}`} className='file_container'>
            <Document file={`data:application/pdf;base64,${file}`} style={{height: '50vh'}}>
                <Page size="A4" pageNumber={1} className="pdfFacture" />
            </Document>
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:15:20