首页 > 解决方案 > React 组件正在无限次重新渲染

问题描述

路由器文件中的所有大多数组件都无限运行。不知道是什么问题。由于这个问题,ajax 请求会发送无限的 GET 请求。

所有文件看起来都与此类似。

import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { apiCall } from "../handlers/api";
import BasicTable from "../reusable/table";
import { loadFields } from "../store/actions/actionCreators";

const header = [
  "Sl.No",
  "Item Code",
  "Item Name",
  "Item Type",
  "UoM",
  "HSN CODE",
  "Specifications",
  "Description",
  "Brand",
  "Price",
];

function Item(props) {
  const [fields, setFields] = useState([]);
  const [render, setRender] = useState(0);
  console.log(fields);

  // useEffect(() => {
  //   props
  //     .loadFields("/items", 0, 20)
  //     .then((res) => {
  //       console.log(res);
  //     })
  //     .catch((err) => console.log(err));
  //   // eslint-disable-next-line react-hooks/exhaustive-deps
  // }, []);
  apiCall("get", "/product", {})
    .then((data) => setFields(data.product))
    .catch((err) => console.log(err));

  const reRender = () => {
    setRender(render + 1);
  };

  return (
    <div>
      <h1>Items</h1>
      <BasicTable reRender={reRender} header={header} body={fields} />
    </div>
  );
}

const mapStateToProps = (state) => ({
  item: state.Items.fields,
});

export default connect(mapStateToProps, { loadFields })(Item);

Routes 文件:这里定义了所有的路由。

import React from "react";
import { Route, BrowserRouter as Router, Switch } from "react-router-dom";
import Home from "./home";
import Supplier from "./supplier";
import Item from "./item";
import Menubar from "./menubar";
import Project from "./project";
import Fields from "./fields";
import User from "./user";
import GeneratePO from "./generatePo";
import PODetails from "./poDetails";
import AddButton from "./addButton";
import AddFields from "./addFields";
import { connect } from "react-redux";
import ViewItems from "../reusable/viewItems";
import AddMaterialForm from "../reusable/addMaterialForm";
import ViewMaterialFormItem from "../reusable/viewMaterialFormItem";
import InventoryHeader from "./inventoryHeader";
import InventoryDetails from "./inventoryDetails";
import AddIntentTable from "../reusable/addIntentTable";
import InventoryIssues from "./inventoryIssues";
import InventoryIndents from "./inventoryIndents";
import ItemForm from "../reusable/itemForm";
import POReport from "../reports/poReport";

function Routers(props) {
  return (
    <React.Fragment>
      <Router>
        <header className="width-max navbar">
          <Menubar />
          <AddButton />
        </header>
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route exact path="/users">
            <User />
          </Route>
          <Route exact path="/items">
            <Item />
          </Route>
          <Route exact path="/suppliers">
            <Supplier />
          </Route>
          <Route exact path="/fields">
            <Fields />
          </Route>
          <Route exact path="/projects">
            <Project />
          </Route>
          <Route exact path="/generatepo">
            <GeneratePO />
          </Route>
          <Route exact path="/inventoryheader">
            <InventoryHeader />
          </Route>
          <Route exact path="/inventorydetails">
            <InventoryDetails />
          </Route>
          <Route path="/items/add">
            <ItemForm type="POST" />
          </Route>
          <Route path="/users/add">
            <AddFields field="/users" data={{}} type="POST" />
          </Route>
          <Route path="/suppliers/add">
            <AddFields field="/suppliers" data={{}} type="POST" />
          </Route>
          <Route path="/fields/add">
            <AddFields field="/fields" data={{}} type="POST" />
          </Route>
          <Route path="/projects/add">
            <AddFields field="/projects" data={{}} type="POST" />
          </Route>
          <Route path="/generatepo/add">
            <AddMaterialForm field="/generatepo" data={{}} type="POST" />
          </Route>
          <Route path="/inventoryheader/add">
            <AddIntentTable field="/inventoryheader" data={{}} type="POST" />
          </Route>
          <Route path="/items/edit/:ID">
            <ItemForm type="PUT" />
          </Route>
          <Route path="/users/edit/:ID">
            <AddFields field="/users" data={props.user} type="PUT" />
          </Route>
          <Route path="/suppliers/edit/:ID">
            <AddFields field="/suppliers" data={props.supplier} type="PUT" />
          </Route>
          <Route path="/fields/edit/:ID">
            <AddFields field="/fields" data={props.field} type="PUT" />
          </Route>
          <Route path="/projects/edit/:ID">
            <AddFields field="/projects" data={props.project} type="PUT" />
          </Route>
          <Route exact path="/inventory/edit">
            <InventoryHeader />
          </Route>
          <Route path="/purchase/edit">
            <GeneratePO />
          </Route>
          <Route path="/generatepo/edit/:ID">
            <AddMaterialForm
              field="/generatepo"
              data={props.materialForm}
              type="PUT"
            />
          </Route>
          <Route path="/inventoryheader/edit/:ID">
            <AddIntentTable
              field="/inventoryheader"
              data={props.inventoryTable}
              type="PUT"
            />
          </Route>
          <Route path="/items/view/:ID">
            <ViewItems field="/items" data={props.item} />
          </Route>
          <Route path="/users/view/:ID">
            <ViewItems field="/users" data={props.user} />
          </Route>
          <Route path="/suppliers/view/:ID">
            <ViewItems field="/suppliers" data={props.supplier} />
          </Route>
          <Route path="/fields/view/:ID">
            <ViewItems field="/fields" data={props.field} />
          </Route>
          <Route path="/projects/view/:ID">
            <ViewItems field="/projects" data={props.project} />
          </Route>
          <Route path="/generatepo/view/:ID">
            <ViewMaterialFormItem
              field="/generatepo"
              data={props.materialForm}
            />
          </Route>
          <Route path="/inventoryheader/view/:ID">
            <ViewItems field="/inventoryheader" data={props.inventoryTable} />
          </Route>
          <Route path="/inventoryissues">
            <InventoryIssues />
          </Route>
          <Route path="/inventoryindents">
            <InventoryIndents />
          </Route>
          <Route path="/podetails">
            <PODetails />
          </Route>
          <Route path="/poreport">
            <POReport />
          </Route>
        </Switch>
      </Router>
    </React.Fragment>
  );
}

const mapStateToProps = (state) => ({
  item: state.Items.fields,
  field: state.Fields.fields,
  project: state.Projects.fields,
  supplier: state.Suppliers.fields,
  user: state.Users.fields,
  materialForm: state.MaterialForm.fields,
  inventoryTable: state.InventoryTable.fields,
});

export default connect(mapStateToProps, null)(Routers);

table.js 文件:这是大多数文件动态使用的可重用组件。

import React, { useState, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Button from "@material-ui/core/Button";
import VisibilityIcon from "@material-ui/icons/Visibility";
import EditIcon from "@material-ui/icons/Edit";
import DeleteIcon from "@material-ui/icons/Delete";
import { BottomScrollListener } from "react-bottom-scroll-listener";
import { connect } from "react-redux";
import { loadFields, removeFields } from "../store/actions/actionCreators";
import { useLocation, useHistory } from "react-router-dom";

const useStyles = makeStyles({
  table: {
    minWidth: 650,
  },
});

function BasicTable(props) {
  const location = useLocation();
  const history = useHistory();
  const [items, setItems] = useState([...props.body]);
  const [limit, setLimit] = useState(20);
  const classes = useStyles();

  useEffect(() => {
    const interval = setInterval(() => setItems([...props.body]), 500);
    return () => {
      clearInterval(interval);
    };
  }, [limit, props.body]);

  const handleDelete = (data) => {
    props.removeFields(location.pathname, data);
    setItems(items.filter((item) => item.id !== data.id));
    props.reRender();
  };

  const handleEdit = (id) => {
    history.push(`${location.pathname}/edit/${id}`);
  };

  const handleView = (id) => {
    history.push(`${location.pathname}/view/${id}`);
  };

  const handleScroll = () => {
    // setItems([
    //   ...items,
    //   ...props.body.slice(
    //     limit,
    //     props.body.length > limit + 20 ? limit + 20 : props.body.length
    //   ),
    // ]);
    // setLimit(limit + 20);
  };
  const tableHeader = props.header.map((item, index) => {
    if (index === 0) {
      return (
        <TableCell key={item}>
          <b>{item}</b>
        </TableCell>
      );
    } else {
      return (
        <TableCell key={item} align="right">
          <b>{item}</b>
        </TableCell>
      );
    }
  });

  const tableContent = items.map((item, index) => {
    return (
      <TableRow key={index}>
        {Object.values(item).map((row, ind) =>
          ind === 0 ? (
            <TableCell key={ind} component="th" scope="row">
              {row}
            </TableCell>
          ) : typeof row === "object" ? (
            String(row.name ? row.name : null)
          ) : (
            <TableCell key={ind} align="right">
              {location.pathname === "/users" && ind === 3 ? "**********" : row}
            </TableCell>
          )
        )}
        {location.pathname === "/inventoryindents" ? (
          <Button variant="outlined" color="primary">
            Open Indent
          </Button>
        ) : (
          <TableCell align="right">
            {/* <VisibilityIcon
              style={{ margin: "5px", cursor: "pointer" }}
              onClick={() => handleView(item.id)}
            /> */}
            <EditIcon
              onClick={() => handleEdit(item.id)}
              style={{ margin: "5px", cursor: "pointer" }}
            />
            <DeleteIcon
              onClick={() => handleDelete(item)}
              style={{ margin: "5px", cursor: "pointer" }}
            />
          </TableCell>
        )}
      </TableRow>
    );
  });

  return (
    <BottomScrollListener onBottom={() => handleScroll()}>
      <TableContainer component={Paper}>
        <Table className={classes.table} aria-label="simple table">
          <TableHead>
            <TableRow>
              {tableHeader}
              <TableCell align="right">
                <b>Actions</b>
              </TableCell>
            </TableRow>
          </TableHead>
          <TableBody>{tableContent}</TableBody>
        </Table>
      </TableContainer>
      <br />
      <br />
      <br />
    </BottomScrollListener>
  );
}

const mapStateToProps = (state) => ({
  state,
});

export default connect(mapStateToProps, { loadFields, removeFields })(
  BasicTable
);

请帮忙

标签: javascriptreactjsreduxreact-router

解决方案


每当它们的状态或道具发生变化时,React 组件会自动重新渲染。状态的简单更新会导致所有用户界面 (UI) 元素自动重新呈现。在您的第一个文件中,您正在进行一些 API 调用,成功更改状态。这将告诉反应重新渲染组件,然后它会再次执行 API 并继续。

使用适当的依赖数组在 useEffect 函数中执行 API 调用等所有副作用。


推荐阅读