javascript - 材料表滞后于我添加的更多行(无法忍受 400 行)
问题描述
我目前正在开发一个实习生应用程序来显示采购部门的订单。它工作得很好,我在开发时数据库中的行数从未超过 40 行。但是当我将数据从实时数据库迁移到我的开发数据库时,该表填满了 400 多行。我立即注意到性能完全走下坡路。
页面渲染非常慢,我们说的是seconds,处理 Inputs 也需要很长时间。我可以通过将分页添加到每页只有 20 行可见的表格来优化性能,但产品所有者只想向下滚动并列出每个订单位置。我寻找材料表的虚拟卷轴,但找不到。以下代码是其中包含表格的组件。我会提出任何建议:
const OrderTable = () => {
const dispatch = useDispatch();
const classes = useStyles();
const orders = useSelector(state => state).allOrders.orders;
const lagerist = useSelector(state => state).allLagerists.lagerists;
const status = useSelector(state => state).allStatus.status;
const currentUser = useSelector(state => state).currentUser.currentUser;
const lagerorts = useSelector(state => state).allLagerorts.lagerorts;
const [dialogOpen, setDialogOpen] = useState(false);
const [viewDialogOpen, setViewDialogOpen] = useState(false);
const [editDialogOpen, setEditDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [rowToUpdate, setRowToUpdate] = useState([]);
const [rowToDelete, setRowToDelete] = useState(0);
const einkäufer = lagerist.filter(lagerist => lagerist.Einkäufer === true);
const [selectedRows, setSelectedRows] = useState([]);
const [rowsToEdit, setRowsToEdit] = useState([]);
const [multiEditOpen, setMultiEditOpen] = useState(false);
const eNummer = useSelector(state => state).allENummer.enummers;
let editPermission = "";
let userPermission = false;
if (currentUser[0] !== undefined) {
editPermission = currentUser[0].Admin ? "always" : "never";
userPermission = currentUser[0].Admin ? true : false;
}
const einkäuferLookup = Object.fromEntries(
einkäufer.map(el => [el.Kuerzel, el.Kuerzel])
);
const statusLookup = Object.fromEntries(
status.map(el => [el.Status, el.Status])
);
const sortedOrders = orders.filter(order => order.Status !== "Abgeschlossen");
const callBackFunctionToDialog = () => {
setDialogOpen(false);
};
const callBackFunctionToEditDialog = () => {
setEditDialogOpen(false);
};
const callBackFunctionToDeleteDialog = () => {
setDeleteDialogOpen(false);
};
const callBackFunctionToMultiEdit = () => {
setMultiEditOpen(false);
};
const handleChecks = (row, checked, column) => {
new Promise((resolve, reject) => {
axios
.put("https://ektool.burriag.ch/api/setaboffertecheck", {
row: row,
valueTobeSet: !checked,
column: column,
})
.then(() => {
axios
.get("https://ektool.burriag.ch/api/getorders")
.then(response => {
dispatch(setOrders(response.data[0]));
})
.catch(err => {
console.log("Err", err);
});
})
.catch(err => {
console.log(err);
reject(err);
});
})
.then(() => {})
.catch(err => {
console.log(err);
});
};
const handleClose = () => {
setMultiEditOpen(false);
};
let artikelcodeLookup = Object.fromEntries(
orders.map(el =>
el !== null ? [el.Artikelkategoriencode, el.Artikelkategoriencode] : false
)
);
//23 more lookup functions similair to the one above
const standardcolumns = [
{
title: "Art-Kat-Code",
field: "Artikelkategoriencode",
editable: "never",
lookup: artikelcodeLookup,
},
{
title: "EK-MA",
field: "Einkäufer",
emptyValue: "______",
render: row => (row.Einkäufer === "" ? "" : row.Einkäufer),
lookup: ekmitarbeiterlookup,
editable: editPermission,
},
{
title: "Datum",
field: "Datum",
type: "date",
editable: "never",
render: row => <div>{moment(row.Datum).format("DD.MM.YYYY")}</div>,
},
{
title: "MA",
field: "Mitarbeiter",
editable: "never",
lookup: mitarbeiterLookup,
},
{
title: "gew. L-Datum",
field: "gewuenschter_Liefertermin",
editable: "never",
type: "date",
render: row => (
<div>
{row.gewuenschter_Liefertermin !== null
? moment(row.gewuenschter_Liefertermin).format("DD.MM.YYYY")
: ""}
</div>
),
cellStyle: (e, rowData) => {
if (
rowData.gewuenschter_Liefertermin <
moment().format("YYYY-MM-DD HH:mm:ss.SSS")
) {
return {
backgroundColor: "#FF4136",
fontWeight: 900,
color: "white",
minWidth: 129.75,
};
}
return { width: 129.75 };
},
},
{
title: "def. L-Datum",
field: "definitiver_Liefertermin",
type: "date",
editable: editPermission,
render: row =>
row.definitiver_Liefertermin === ""
? "______"
: moment(row.definitiver_Liefertermin).format("DD-MM-YYYY"),
emptyValue: "______",
cellStyle: (e, rowData) => {
if (
rowData.definitiver_Liefertermin != null &&
moment(rowData.definitiver_Liefertermin).format("DD-MM-YYYY") >
moment(rowData.gewuenschter_Liefertermin).format("DD-MM-YYYY")
) {
return {
backgroundColor: "#FFDC00",
fontWeight: 900,
color: "white",
};
}
},
},
{
title: "Zeichnungsnummer",
field: "Zeichnungsnummer",
lookup: zeichnungsnummerlookup,
editable: "never",
},
{
title: "Artikelnummer",
field: "Artikelnummer",
lookup: artikelnummerlookup,
editable: "never",
},
{
title: "Beschreibung",
field: "Beschreibung",
filterComponent: props => {
return (
<TextField
onChange={e =>
props.onFilterChanged(
props.columnDef.tableData.id,
e.target.value
)
}
/>
);
},
editable: "never",
},
{
title: "Menge",
field: "Menge",
editable: "never",
filterComponent: props => {
return (
<TextField
onChange={e =>
props.onFilterChanged(
props.columnDef.tableData.id,
e.target.value
)
}
/>
);
},
},
{
title: "Einheit",
field: "Einheit",
lookup: einheitenlookup,
editable: "never",
},
{
title: "Werkstoff",
field: "Werkstoff",
editable: "never",
lookup: werkstofflookup,
cellStyle: (e, rowData) => {
if (rowData.Werkstoff !== "S235JR" && rowData.Werkstoff != null) {
return {
backgroundColor: "#7FDBFF",
fontWeight: 900,
color: "white",
};
}
},
},
{
title: "Bem.",
field: "Bemerkungen",
editable: "never",
filterComponent: props => {
return (
<TextField
onChange={e =>
props.onFilterChanged(
props.columnDef.tableData.id,
e.target.value
)
}
/>
);
},
render: row => (
<div>
<Dialog text={row.Bemerkungen} />
</div>
),
},
{
title: "Lagerort",
field: "Lagerort",
render: row => (row.Lagerort === "" ? "______" : row.Lagerort),
emptyValue: "______",
editable: editPermission,
lookup: lagerortlookup,
},
{
title: "Lieferant",
field: "Lieferant",
emptyValue: "______",
render: row => (row.Lieferant === "" ? "______" : row.Lieferant),
editable: editPermission,
lookup: lieferantlookup,
},
{
title: "Off.",
field: "Offerte",
type: "boolean",
editable: "never",
render: row => (
<div>
<FormControlLabel
control={
<Checkbox
checked={row.Offerte}
onClick={() => {
if (userPermission === true) {
handleChecks(row, row.Offerte, "Offerte");
}
}}
name="checkedB"
color="secondary"
/>
}
/>
</div>
),
},
{
title: "AB",
field: "AB",
editable: "never",
type: "boolean",
render: row => (
<div>
<FormControlLabel
control={
<Checkbox
checked={row.AB}
onClick={() => {
if (userPermission === true) {
handleChecks(row, row.AB, "AB");
}
}}
name="checkedB"
/>
}
/>
</div>
),
},
{
title: "E-Nr.",
field: "ENummer",
editable: "never",
render: row => {
if (editPermission) {
const enummerOfRow = eNummer.filter(
enummer => enummer.Projekt === row.ProjektNr
);
const enummerArray = enummerOfRow.map((enummer, index) => {
return {
ENummer: enummer.ENummer,
};
});
return (
<>
<Select
style={{ width: 120 }}
labelId="demo-simple-select-label"
id="demo-simple-select"
inputProps={{ "aria-label": "Without label" }}
defaultValue={""}
value={row.ENummer}
onChange={e => {
return new Promise((resolve, reject) => {
axios
.put("https://ektool.burriag.ch/api/updateordercell", {
column: "ENummer",
RecID: row.RecID,
newValue: e.target.value,
})
.then(res => {
axios
.get("https://ektool.burriag.ch/api/getorders")
.then(response => {
dispatch(setOrders(response.data[0]));
resolve();
})
.catch(err => {
reject(err);
console.log("Err", err);
});
})
.catch(err => {
reject(err);
console.log(err);
});
});
}}
renderValue={selected => {
return <>{selected}</>;
}}
>
<MenuItem value="" disabled>
EB-Nummer ausw.
</MenuItem>
<MenuItem value="">Leer lassen</MenuItem>
{enummerArray.map((enummer, index) => {
console.log(enummer);
return (
<MenuItem key={index} value={enummer.ENummer}>
{enummer.ENummer}
</MenuItem>
);
})}
</Select>
</>
);
} else {
return row.ENummer;
}
},
lookup: enummerlookup,
},
{
title: "Projekt",
field: "ProjektNr",
editable: "never",
lookup: projektnrlookup,
},
{
title: "Eb-Nr.",
field: "EBNummer",
editable: editPermission,
render: row => (row.EBNummer === "" ? "______" : row.EBNummer),
emptyValue: "______",
lookup: ebnummerlookup,
cellStyle: (e, rowData) => {
if (rowData.EBNummer != null && rowData.Status === "In Bearbeitung") {
return { backgroundColor: "#FFDC00" };
}
if (rowData.EBNummer != null && rowData.Status !== "In Bearbeitung") {
return { backgroundColor: "#2ECC40", color: "white" };
}
},
},
{
title: "EK-Bemerkung",
field: "EKBemerkungen",
render: row => (row.EKBemerkung === "" ? "______" : row.EKBemerkung),
emptyValue: "______",
editable: editPermission,
filterComponent: props => {
return (
<TextField
onChange={e =>
props.onFilterChanged(
props.columnDef.tableData.id,
e.target.value
)
}
/>
);
},
},
{
title: "Status",
field: "Status",
editable: editPermission,
lookup: statusLookup,
cellStyle: (e, rowData) => {
if (rowData.Status === "Neu") {
return { backgroundColor: "#fdea6b" };
}
if (rowData.Status === "Verzögert") {
return { backgroundColor: "#FF851B", color: "white" };
}
},
},
];
const downloadPDF = rowData => {
const doc = new jsPDF("landscape");
doc.text("Uploadfreigabe" + moment().format("dd/mm/yyyy"), 20, 10);
doc.autoTable({
margin: { left: 5, right: 5 },
columns: standardcolumns.map(col => ({ ...col, dataKey: col.field })),
body: rowData,
});
doc.save("Uploadfreigabe" + moment().format("dd/mm/yyyy"));
console.log(rowData);
};
return (
<div>
<MaterialTable
style={{ fontFamily: "'Open Sans', sans-serif", height: "100%" }}
className={classes.root}
title={<div className={classes.h1}>Bestellübersicht</div>}
data={sortedOrders}
columns={
standardcolumns
// localStorage.getItem("currentLayout") === null
// ? standardcolumns
// : currentLayoutColumns
}
onSelectionChange={rows => setSelectedRows(rows)}
cellEditable={{
onCellEditApproved: (newValue, oldValue, rowData, columnDef) => {
return new Promise((resolve, reject) => {
axios
.put("https://ektool.burriag.ch/api/updateordercell", {
column: columnDef.field,
RecID: rowData.RecID,
newValue: newValue,
})
.then(res => {
axios
.get("https://ektool.burriag.ch/api/getorders")
.then(response => {
dispatch(setOrders(response.data[0]));
resolve();
})
.catch(err => {
reject(err);
console.log("Err", err);
});
})
.catch(err => {
reject(err);
console.log(err);
});
});
},
}}
options={{
filtering: true,
selection: true,
addRowPosition: "first",
columnsButton: true,
showSelectAllCheckbox: true,
paging: false,
headerStyle: {
fontFamily: "'Open Sans', sans-serif",
backgroundColor: "#ddd",
fontWeight: 600,
textAlign: "left",
},
}}
actions={[
{
icon: "add",
tooltip: "Bestellung hinzufügen",
isFreeAction: true,
onClick: () => setDialogOpen(true),
},
{
icon: "edit",
tooltip: "Bestellung editieren",
onClick: (event, rowData) => {
setRowToUpdate(rowData);
setEditDialogOpen(true);
},
position: "row",
hidden: !userPermission,
},
{
icon: "delete",
tooltip: "Bestellung löschen",
onClick: (event, rowData) => {
setRowToDelete(rowData.RecID);
setDeleteDialogOpen(true);
},
position: "row",
hidden: !userPermission,
},
{
icon: "save_alt",
// isFreeAction,
tooltip: "Exportiere die Daten",
onClick: () => exportAllSelectedRows(selectedRows),
},
rowData => ({
name: "pdf",
icon: () => <PrintIcon />,
tooltip: "PDF-Export",
onClick: (event, rowData) => downloadPDF(rowData),
disabled: false,
// position: "row",
}),
rowData => ({
name: "edit",
icon: () => <EditLocation />,
tooltip: "Zeilenübergreifende Editierung",
onClick: (event, rowData) => {
setRowsToEdit(rowData);
setMultiEditOpen(true);
},
disabled: false,
}),
]}
components={{
Row: props => {
if (userPermission === true) {
return (
<MTableBodyRow
{...props}
onDoubleClick={e => {
setRowToUpdate(props.data);
setEditDialogOpen(true);
}}
/>
);
} else {
return <MTableBodyRow {...props} />;
}
},
EditField: props => {
switch (props.columnDef.title) {
case "def. L-Datum":
return (
<div style={{ minWidth: 150 }}>
<Grid
container
direction="row"
alignContent="center"
justify="center"
>
<Grid item xs={12}>
<KeyboardDatePicker
error="none"
fullWidth
clearable
autoOk
onChange={e =>
props.onChange(e != null ? e._d : null)
}
value={props.value}
minDate={new Date()}
format="DD-MM-YYYY"
/>
</Grid>
</Grid>
</div>
);
case "EK-Bemerkung":
return (
<>
<textarea
id="outlined-basic"
variant="outlined"
style={{ minWidth: 150 }}
value={props.value}
onChange={e =>
props.onChange(e !== null ? e.target.value : null)
}
/>
</>
);
case "EK-MA":
return (
<>
<Select
style={{ width: 80 }}
labelId="demo-simple-select-label"
id="demo-simple-select"
inputProps={{ "aria-label": "Without label" }}
value={props.value}
onChange={e => {
props.onChange(einkäuferLookup[e.target.value]);
}}
renderValue={selected => {
return <>{selected}</>;
}}
>
<MenuItem value="" disabled>
Einkäufer auswählen
</MenuItem>
{einkäufer.map((einkäufer, index) => {
return (
<MenuItem key={index} value={einkäufer.Kuerzel}>
{einkäufer.Name}
</MenuItem>
);
})}
</Select>
</>
);
case "Lagerort":
return (
<>
<Select
style={{ width: 80 }}
labelId="demo-simple-select-label"
id="demo-simple-select"
inputProps={{ "aria-label": "Without label" }}
value={props.value}
onChange={e => {
props.onChange(e.target.value);
}}
renderValue={selected => {
return <>{selected}</>;
}}
>
<MenuItem value="" disabled>
Lagerort auswählen
</MenuItem>
{lagerorts.map((lagerort, index) => {
return (
<MenuItem key={index} value={lagerort.Name}>
{lagerort.Name}
</MenuItem>
);
})}
</Select>
</>
);
case "Lieferant":
return (
<TextField
id="outlined-basic"
variant="outlined"
style={{ minWidth: 150 }}
value={props.value}
onChange={e =>
props.onChange(e !== null ? e.target.value : null)
}
/>
);
case "Eb-Nr.": {
return (
<TextField
id="outlined-basic"
variant="outlined"
style={{ minWidth: 150 }}
value={props.value}
onChange={e =>
props.onChange(e !== null ? e.target.value : null)
}
/>
);
}
case "EK-Bemerkung": {
return (
<TextField
id="outlined-basic"
variant="outlined"
style={{ minWidth: 150 }}
value={props.value}
onChange={e =>
props.onChange(e !== null ? e.target.value : null)
}
/>
);
}
case "Status":
return (
<>
<Select
style={{ width: 120 }}
labelId="demo-simple-select-label"
id="demo-simple-select"
inputProps={{ "aria-label": "Without label" }}
value={props.value}
onChange={e => {
props.onChange(statusLookup[e.target.value]);
}}
renderValue={selected => {
return <>{selected}</>;
}}
>
<MenuItem value="" disabled>
Status setzen
</MenuItem>
{status.map((status, index) => {
return (
<MenuItem key={index} value={status.Status}>
{status.Status}
</MenuItem>
);
})}
</Select>
</>
);
default:
// Anweisungen werden ausgeführt,
// falls keine der case-Klauseln mit expression übereinstimmt
break;
}
},
FilterRow: props => {
return (
<MTableFilterRow
{...props}
localization={{
dateTimePickerLocalization: de,
}}
/>
);
},
}}
/>
<OrderDialog
dialogOpen={dialogOpen}
callBackFunctionToDialog={callBackFunctionToDialog}
/>
<EditDialog
dialogOpen={editDialogOpen}
rowData={rowToUpdate}
callBackFunctionToEditDialog={callBackFunctionToEditDialog}
/>
<DeleteOrderDialog
dialogOpen={deleteDialogOpen}
rowToDelete={rowToDelete}
callBackFunctionToDeleteDialog={callBackFunctionToDeleteDialog}
/>
{/* <ViewDialog
dialogOpen={viewDialogOpen}
currentColumns={currentLayoutColumns}
setCurrentColumns={setCurrentLayoutColumns}
callBackFunctionToViewDialog={callBackFunctionToViewDialog}
/> */}
<MultiOrderEditDialog
multiEditOpen={multiEditOpen}
onClose={handleClose}
rowsToEdit={rowsToEdit}
callBackFunctionToMultiEdit={callBackFunctionToMultiEdit}
/>
</div>
);
};
export default OrderTable;
解决方案
推荐阅读
- javascript - 打开 NonBootstrap 模式以使用 PHP 和 JavaScript 更新/编辑表中的行
- c++ - 为什么第二次调用 name() 打印“Alex . n”?
- ios - 快速在 UIImageView 上创建缩放
- c - 如何利用结构数组根据用户输入输出给定的结构
- r - R ImageMagick。如何用单一颜色填充图像的子集
- ios - 为什么 iOs 代码使用如此多的内存和 CPU
- arrays - 如何使用 Fortran 90 将一维数组的数据写入文件的下一列?
- react-native - NodeJS 是 React Native 应用程序背后的唯一服务器吗?
- android - 在onCreate中使用getActivity时如何让onCreate在onCreateView之前加载?
- php - Woocommerce 自定义订单状态更改日期