React中MaterialTable折叠面板API加载数据不显示问题求助
问题根源
你当前使用全局的acc_rata和acc_drata状态变量存储所有行的折叠面板数据,导致所有行的detailPanel共享同一状态:
- 当打开某一行的Accordion调用API时,全局状态更新,但当前行的detailPanel已经渲染完成,无法自动读取新状态;只有当其他行触发组件重新渲染时,才会读取已更新的全局状态,所以数据延迟显示。
- 多行行展开时,全局状态会被最后一次API调用覆盖,导致所有折叠面板显示最后一行的数据。
解决方案:拆分独立组件维护行内状态
将detailPanel的内容拆分为独立组件,每个组件维护自己的状态,确保每行的折叠面板数据相互独立,API调用后能实时更新视图。
步骤1:创建独立的DetailPanel组件
import React, { useState } from 'react'; import { Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core'; import ArrowDownwardOutlinedIcon from '@material-ui/icons/ArrowDownwardOutlined'; import { searchTbl_Rata } from '../../repo/tbl_rataRepo'; import { searchTbl_Dettagli_Rata } from '../../repo/tbl_dettagli_rataRepo'; const DetailPanel = ({ rowData }) => { // 每个组件独立维护自己的状态 const [acc_rata, setAccordionRata] = useState([]); const [acc_drata, setAccordionDetailRata] = useState([]); const [loadingRata, setLoadingRata] = useState(false); // 获取Rate数据,避免重复调用API const handleRata = async () => { if (acc_rata.length > 0) return; setLoadingRata(true); const res = await searchTbl_Rata(1, "", rowData.idDoc); setAccordionRata(res.data.data.data); setLoadingRata(false); }; // 获取Rate详情数据 const handleDettagliRata = async () => { if (acc_drata.length > 0) return; const res1 = await searchTbl_Dettagli_Rata(1, "", rowData.idDoc); setAccordionDetailRata(res1.data.data.data); }; return ( <div> <Accordion> <AccordionSummary expandIcon={<ArrowDownwardOutlinedIcon />} aria-controls="panel1a-content" id="panel1a-header" > Dettaglio del documento </AccordionSummary> <AccordionDetails> <div style={{ columns: 3, width: '100%', responsive: true, }} > <ul style={{ fontSize: '14px' }}> <li>Catena Servizio: {rowData.idCatenaServizio}</li> <li>Commessa: {rowData.idCommessa}</li> <li>Spedizione Racc: {rowData.spedRacc}</li> <li>Ricezione Sped: {rowData.spedRic}</li> <li>Nome Documento: {rowData.DocNomeFile}</li> <li>Nome Documento Cliente: {rowData.DocNomeFileCliente}</li> <li>ID Cliente sul documento: {rowData.docIDCliente}</li> <li>#Documento: {rowData.docNum}</li> <li>Data documento: {rowData.docData}</li> <li>Destinatario 2: {rowData.docDestinatario2}</li> <li>Destinatario 3: {rowData.docDestinatario3}</li> <li>Destinatario 4: {rowData.docDestinatario4}</li> <li>Destinatario 5: {rowData.docDestinatario5}</li> <li>Destinatario 6: {rowData.docDestinatario6}</li> <li>Codice Avvio: {rowData.codiceAvvio}</li> <li>Dati 1: {rowData.dati1}</li> <li>Dati 2: {rowData.dati2}</li> <li>Dati 3: {rowData.dati3}</li> <li>Dati 4: {rowData.dati4}</li> <li>Dati 5: {rowData.dati5}</li> <li>Spedito: {rowData.spedito}</li> <li>Nome Immagine: {rowData.nomeImmagine}</li> <li>Pagamento abilitato: {rowData.pagamentoAbilitato}</li> <li>UltimaModifica: {rowData.lastUpdate}</li> </ul> </div> </AccordionDetails> </Accordion> <Accordion> <AccordionSummary expandIcon={<ArrowDownwardOutlinedIcon />} aria-controls="panel1a-content" id="panel1a-header" onClickCapture={handleRata} > Rate associate </AccordionSummary> <AccordionDetails> <div style={{ columns: 3, width: '100%', }} > <ul style={{ fontSize: '14px' }}> {loadingRata ? ( <li>Caricamento...</li> ) : acc_rata.length === 0 ? ( <li>Nessuna rata associata</li> ) : ( acc_rata.map(y => ( <li key={y.idBol}> {y.idBol} </li> )) )} </ul> </div> </AccordionDetails> </Accordion> <Accordion> <AccordionSummary expandIcon={<ArrowDownwardOutlinedIcon />} aria-controls="panel1a-content" id="panel1a-header" onClickCapture={handleDettagliRata} > Dettaglio delle rate </AccordionSummary> <AccordionDetails> <div style={{ columns: 3, width: '100%', }} > <ul style={{ fontSize: '14px' }}> {acc_drata.length === 0 ? ( <li>Nessun dettaglio disponibile</li> ) : ( acc_drata.map(adr => ( <li key={adr.idBol}> idBol: {adr.idBol} </li> )) )} </ul> </div> </AccordionDetails> </Accordion> </div> ); }; export default DetailPanel;
步骤2:修改父组件的detailPanel配置
在原Tbl_DocumentoTable组件中,删除全局的acc_rata、acc_drata状态以及对应的handleRata、handleDettagliRata函数,然后修改detailPanel的render逻辑:
// 导入新创建的DetailPanel组件 import DetailPanel from './DetailPanel'; // ... 其他代码保持不变 detailPanel={[ { tooltip: 'Dettaglio', icon: '+', openIcon: '-', render: rowData => <DetailPanel rowData={rowData} />, } ]}
额外优化
- 添加加载状态提示,提升用户体验
- 判断数据是否已加载,避免重复调用API
- 空数据时显示友好提示
内容的提问来源于stack exchange,提问作者64Bit1990
相关产品推荐
相关产品推荐

