React-在API调用后,动态地将数据呈现为手风琴



我正在开发一个管理React应用程序。在应用程序中,我有一个表(MaterialTable(,其中显示了每行的详细信息,并提供了detailPanel选项。在细节面板中,我有三个accordion,第一个填充了表的rowData,而另外两个必须在API调用之后填充。

但我有以下问题:当我打开一行的详细信息(例如第3行(,然后单击第二个或第三个手风琴时,数据无法正确检索。通过点击另一行(示例行5(,可以正确地检索和显示数据,但它不是与行5有关的数据,而是与行3有关的数据。

因此,我在更新手风琴时总是晚一步。

你有什么建议吗?

  • myCode:
import MaterialTable from "material-table";
import React, { useEffect, useState } from "react";
import tableIcons from "../templates/TableIcons";
import getColumns from "./Tbl_DocumentoColumns";
import Edit from "@material-ui/icons/Edit";
import {
Accordion,
AccordionSummary,
AccordionDetails,
} from "@material-ui/core";
import { Switch } from "@material-ui/core";
import { withRouter } from "react-router";
import { AddBox } from "@material-ui/icons";
import ArrowDownwardOutlinedIcon from "@material-ui/icons/ArrowDownwardOutlined";
import {
deleteTbl_Documento,
getTbl_Documento,
} from "../../repo/tbl_documentoRepo";
import { searchRata } from "../../repo/tbl_rataRepo";
import { searchDettaglioRata } from "../../repo/tbl_dettagli_rataRepo";
import { Loading } from "../templates/Loading";
/*
Documentation on developing the Material-Table can be found at https://material-table.com/
*/
const Tbl_DocumentoTable = (props) => {
const history = props.history;
const [columns, setColumns] = useState(getColumns({}));
//const [rata, setAccordionRata] = useState({idDoc: ""});
//const [drata, setAccordionDetailRata] = useState({idDoc: ""});
const [loading, setLoading] = useState(false);
const [rata, setIdDocR] = useState({ iddoc: "" });
const [drata, setIdDocDR] = useState({ iddoc: "" });
const [acc_rata, setAccordionR] = useState([]);
const [acc_drata, setAccordionDR] = useState([]);
//Here we call delete
const handleRowDelete = (oldData, resolve) => {
setLoading(true);
deleteTbl_Documento(oldData.idDoc)
.then((res) => {
resolve();
setLoading(false);
})
.catch((error) => {
resolve();
setLoading(false);
});
};
//Settiamo l'idDoc di riferimento per la rata
const handleRata = (evt) => {
setIdDocR({ iddoc: evt });
};
//Settiamo l'idDoc di riferimento per il dettaglio rata
const handleDettagliRata = (evt) => {
setIdDocDR({ iddoc: evt });
};
useEffect(() => {
const R = async () => {
const r = await searchRata(rata.iddoc);
setAccordionR(r.data.data.data);
};
R();
console.log(acc_rata);
}, [rata.iddoc]);
useEffect(() => {
const DR = async () => {
const r = await searchDettaglioRata(drata.iddoc);
setAccordionDR(r.data.data.data);
};
DR();
console.log(acc_drata);
}, [drata.iddoc]);
return (
<div>
<MaterialTable
style={{
marginLeft: 30,
responsive: true,
marginTop: 50,
marginRight: 30,
}}
minRows={15}
title="Lista dei documenti"
columns={columns}
data={async (query) => {
setLoading(true);
const res = await getTbl_Documento(
query.page,
query.pageSize,
query.search
);
setLoading(false);
return {
data: res.data,
page: query.page,
totalCount: parseInt(res.total),
};
}}
detailPanel={[
{
tooltip: "Dettaglio",
icon: "+",
openIcon: "-",
render: (rowData) => {
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(rowData.idDoc)}
>
Rate associate
</AccordionSummary>
<AccordionDetails data={acc_rata}>
<div
style={{
columns: 3,
width: "100%",
}}
>
<ul style={{ fontSize: "14px" }}>
{acc_rata.map((y) => {
console.log(y.idBol);
return <li key={y.idBol}>{y.idBol}</li>;
})}
</ul>
</div>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary
expandIcon={<ArrowDownwardOutlinedIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
onClickCapture={() => handleDettagliRata(rowData.idDoc)}
>
Dettaglio delle rate
</AccordionSummary>
<AccordionDetails data={acc_drata}>
<div
style={{
columns: 3,
width: "100%",
}}
>
<ul style={{ fontSize: "14px" }}>
{acc_drata.map((adr) => {
return <li key={adr.idBol}>idBol: {adr.idBol}</li>;
})}
</ul>
</div>
</AccordionDetails>
</Accordion>
</div>
);
},
},
]}
options={{
sorting: true,
actionsColumnIndex: -1,
pageSize: 20,
toolbar: true,
paging: true,
responsive: true,
exportButton: true,
exportAllData: true,
exportFileName: "ListaTributi",
}}
onRowClick={(event, rowData, togglePanel) => togglePanel()}
actions={[
{
icon: () => <Edit />,
tooltip: "Edit",
onClick: (event, rowData) => {
history.push({
pathname: `/tbl_documento/update/${rowData.idDoc}`,
user: rowData,
});
},
},
{
icon: () => <AddBox variant="contained" color="secondary" />,
tooltip: "Add New",
// This makes add button to appear in table toolbar instead for each row
isFreeAction: true,
onClick: (event, rowData) => {
history.push("/tbl_documento/add");
},
},
]}
icons={tableIcons}
editable={{
onRowDelete: (oldData) =>
new Promise((resolve) => {
handleRowDelete(oldData, resolve);
}),
}}
/>
</div>
);
};
export default withRouter(Tbl_DocumentoTable);

您在一个组件中混合了几个关注点。请重新访问文档以进行思考和反应。也就是说,您可以使用useEffect钩子将DetailPanel的呈现逻辑封装在一个组件中,以加载两种数据RataDettaglioRata,并使所有这些逻辑仅依赖于rowData。

const DetailPanel = ({ rowData }) => {
const [acc_rata, setAccordionR] = useState([]);
const [acc_drata, setAccordionDR] = useState([]);
useEffect(() => {
const loadData = async () => {
const r = await searchRata(rowData.iddoc);
const dr = await searchDettaglioRata(rowData.iddoc);
setAccordionR(r.data.data.data);
setAccordionDR(dr.data.data.data);
};
loadData();
}, [rowData.iddoc]);
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"
>
Rate associate
</AccordionSummary>
<AccordionDetails data={acc_rata}>
<div
style={{
columns: 3,
width: "100%",
}}
>
<ul style={{ fontSize: "14px" }}>
{acc_rata.map((y) => {
return <li key={y.idBol}>{y.idBol}</li>;
})}
</ul>
</div>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary
expandIcon={<ArrowDownwardOutlinedIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
Dettaglio delle rate
</AccordionSummary>
<AccordionDetails data={acc_drata}>
<div
style={{
columns: 3,
width: "100%",
}}
>
<ul style={{ fontSize: "14px" }}>
{acc_drata.map((adr) => {
return <li key={adr.idBol}>idBol: {adr.idBol}</li>;
})}
</ul>
</div>
</AccordionDetails>
</Accordion>
</div>
);
};

这会清理一点你的主要成分

const Tbl_DocumentoTable = (props) => {
const history = props.history;
const [columns, setColumns] = useState(getColumns({}));
//const [rata, setAccordionRata] = useState({idDoc: ""});
//const [drata, setAccordionDetailRata] = useState({idDoc: ""});
const [loading, setLoading] = useState(false);
//Here we call delete
const handleRowDelete = (oldData, resolve) => {
setLoading(true);
deleteTbl_Documento(oldData.idDoc)
.then((res) => {
resolve();
setLoading(false);
})
.catch((error) => {
resolve();
setLoading(false);
});
};
return (
<div>
<MaterialTable
style={{
marginLeft: 30,
responsive: true,
marginTop: 50,
marginRight: 30,
}}
minRows={15}
title="Lista dei documenti"
columns={columns}
data={async (query) => {
setLoading(true);
const res = await getTbl_Documento(
query.page,
query.pageSize,
query.search
);
setLoading(false);
return {
data: res.data,
page: query.page,
totalCount: parseInt(res.total),
};
}}
detailPanel={[
{
tooltip: "Dettaglio",
icon: "+",
openIcon: "-",
render: (rowData) => {
return <DetailPanel rowData={rowData} />;
},
},
]}
options={{
sorting: true,
actionsColumnIndex: -1,
pageSize: 20,
toolbar: true,
paging: true,
responsive: true,
exportButton: true,
exportAllData: true,
exportFileName: "ListaTributi",
}}
onRowClick={(event, rowData, togglePanel) => togglePanel()}
actions={[
{
icon: () => <Edit />,
tooltip: "Edit",
onClick: (event, rowData) => {
history.push({
pathname: `/tbl_documento/update/${rowData.idDoc}`,
user: rowData,
});
},
},
{
icon: () => <AddBox variant="contained" color="secondary" />,
tooltip: "Add New",
// This makes add button to appear in table toolbar instead for each row
isFreeAction: true,
onClick: (event, rowData) => {
history.push("/tbl_documento/add");
},
},
]}
icons={tableIcons}
editable={{
onRowDelete: (oldData) =>
new Promise((resolve) => {
handleRowDelete(oldData, resolve);
}),
}}
/>
</div>
);
};
export default withRouter(Tbl_DocumentoTable);

您遇到的问题可能是在更新多个状态并通过useEffect加载同一组件中的数据时产生的间隙。

最新更新