首页  >  问答  >  正文

为什么我收到“太多重新渲染。React 限制了渲染次数”?我的无限循环在哪里

我的下面的代码运行,但我收到“太多重新渲染”错误。我不知道为什么。如果我取出双开关并将其基于一个单位(例如价格),那么它就可以工作。但是,我找不到我的代码在哪里导致无限循环。网上说我可能错误地使用了 useState 。任何帮助表示赞赏。我是个菜鸟,所以请理解我可能做了一些愚蠢的事情!无论如何,学习是很棒的!谢谢。

import React from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import TableSortLabel from "@mui/material/TableSortLabel";
import { useState } from "react";


function createData(number, item, qty, price) {
  return { number, item, qty, price };
}

const rows = [
  createData(1, "Apple", 5, 3),
  createData(2, "Orange", 2, 2),
  createData(3, "Grapes", 3, 1),
  createData(4, "Tomato", 2, 1.6),
  createData(5, "Mango", 1.5, 4)
];

export default function SortedTable() {
  const [rowData, setRowData] = useState(rows);
  const [orderDirection, setOrderDirection] = useState("asc");
  const [orderUnit, setOrderUnit] = useState("number");

  const sortArray = (arr, orderBy, orderUn) => {
    switch (orderUn) {
      case "number": 
      default:
        switch (orderBy) {
          case "asc":
          default:
            return arr.sort((a, b) =>
              a.number > b.number ? 1 : b.number > a.number ? -1 : 0
            );
          case "desc":
            return arr.sort((a, b) =>
              a.number > b.number ? 1 : b.number > a.number ? -1 : 0
            );
        }
      case "item": 
      switch (orderBy) {
        case "asc":
        default:
          return arr.sort((a, b) =>
            a.item > b.item ? 1 : b.item > a.item ? -1 : 0
          );
        case "desc":
          return arr.sort((a, b) =>
            a.item < b.item ? 1 : b.item < a.item ? -1 : 0
          );
      }
      case "qty": 
      switch (orderBy) {
        case "asc":
        default:
          return arr.sort((a, b) =>
            a.qty > b.qty ? 1 : b.qty > a.qty ? -1 : 0
          );
        case "desc":
          return arr.sort((a, b) =>
            a.qty < b.qty ? 1 : b.qty < a.qty ? -1 : 0
          );
      }
      case "price": 
      switch (orderBy) {
        case "asc":
        default:
          return arr.sort((a, b) =>
            a.price > b.price ? 1 : b.price > a.price ? -1 : 0
          );
        case "desc":
          return arr.sort((a, b) =>
            a.price < b.price ? 1 : b.price < a.price ? -1 : 0
          );
      }
    }
  };
 


  const handleSortRequest = (unit) => {
    setOrderUnit(orderUnit === unit); 
    setRowData(sortArray(rows, orderDirection, orderUnit));
    setOrderDirection(orderDirection === "asc" ? "desc" : "asc");
  };

  return (
    <TableContainer component={Paper}>
      <Table aria-label="simple table" >
        <TableHead>
          <TableRow>
            <TableCell align="center" onClick={handleSortRequest("number")}><TableSortLabel active={true} direction={orderDirection}>
              S.No
            </TableSortLabel></TableCell>

            <TableCell align="center" onClick={handleSortRequest("item")}><TableSortLabel active={true} direction={orderDirection}>
              Item
            </TableSortLabel></TableCell>

            <TableCell align="center" onClick={handleSortRequest("qty")}><TableSortLabel active={true} direction={orderDirection}>
              Quantity&nbsp;(kg)
            </TableSortLabel></TableCell>

            <TableCell align="center" onClick={handleSortRequest("price")}>
              <TableSortLabel active={true} direction={orderDirection}>
                Price&nbsp;($)
              </TableSortLabel>
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rowData.map((row) => (
            <TableRow key={row.number}>
              <TableCell width="100" component="td" scope="row" align="center">
                {row.number}
              </TableCell>
              <TableCell align="center">{row.item}</TableCell>
              <TableCell align="center">{row.qty}</TableCell>
              <TableCell align="center">{row.price}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

我正在尝试使每一列都可以根据单击的列进行排序。额外的问题,为什么我的标题在渲染时与下面的列不匹配。

P粉946437474P粉946437474424 天前497

全部回复(1)我来回复

  • P粉801904089

    P粉8019040892023-09-15 11:54:02

    您需要传递函数引用,而不是直接调用函数。 这样,该函数将仅在事件发生时调用,而不是在组件渲染时立即调用。

    onClick={() => handleSortRequest("item")}

    我还重构了您的 sortArray 函数以使其可读。如果是错的。请不要打扰它。 :D

    const sortArray = useCallback((arr, orderBy, orderUn) => {
        const compare = (a, b, prop, order) => {
          if (order === "asc") {
            return a[prop] > b[prop] ? 1 : b[prop] > a[prop] ? -1 : 0;
          } else {
            return a[prop] < b[prop] ? 1 : b[prop] < a[prop] ? -1 : 0;
          }
        };
    
        switch (orderUn) {
          case "number":
          default:
            return arr.sort((a, b) => compare(a, b, "number", orderBy));
    
          case "item":
            return arr.sort((a, b) => compare(a, b, "item", orderBy));
    
          case "qty":
            return arr.sort((a, b) => compare(a, b, "qty", orderBy));
    
          case "price":
            return arr.sort((a, b) => compare(a, b, "price", orderBy));
        }
      }, []);

    使用 useCallback 来防止在依赖关系未更改时不必要地重新渲染

    const handleSortRequest = useCallback(
        (unit) => {
          setOrderUnit(orderUnit === unit);
          setRowData(sortArray(rows, orderDirection, orderUnit));
          setOrderDirection(orderDirection === "asc" ? "desc" : "asc");
        },
        [orderDirection, orderUnit, sortArray]
      );

    希望这些对您有帮助。

    回复
    0
  • 取消回复