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

React中MaterialTable折叠面板API加载数据不显示问题求助

问题根源

你当前使用全局的acc_rata和acc_drata状态变量存储所有行的折叠面板数据,导致所有行的detailPanel共享同一状态:

  1. 当打开某一行的Accordion调用API时,全局状态更新,但当前行的detailPanel已经渲染完成,无法自动读取新状态;只有当其他行触发组件重新渲染时,才会读取已更新的全局状态,所以数据延迟显示。
  2. 多行行展开时,全局状态会被最后一次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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 12:36:16