首页 > 解决方案 > 材料表滞后于我添加的更多行(无法忍受 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;

标签: javascriptreactjsoptimizationreact-reduxmaterial-table

解决方案


推荐阅读