使用 React Hooks 和 Redux 重新渲染太多

Joh*_*son 0 javascript lodash reactjs react-redux

我有一个显示卡片列表的组件。我正在尝试对表格行进行排序,但遇到了一些问题。当我转到页面时,出现以下错误:

错误:重新渲染过多。React 限制渲染次数以防止无限循环。

它指向这条线

setData(_.sortBy(filteredData.reverse()));
Run Code Online (Sandbox Code Playgroud)

这是我的完整组件代码。任何人都可以看到我正在尝试做的事情有问题吗?

import React, { useState } from "react";
import Search from "./Search";
import TimeAgo from "react-timeago";
import { useSelector, useDispatch, connect } from "react-redux";
import { Table } from "semantic-ui-react";
import { searchChange } from "../reducers/searchReducer";
import _ from "lodash";
// import { useField } from "../hooks";

const searchCards = ({ baseball, search }) => {
  return search
    ? baseball.filter(a =>
        a.title[0].toLowerCase().includes(search.toLowerCase())
      )
    : baseball;
};

const Cards = props => {
  const [column, setColumn] = useState(null);
  const [direction, setDirection] = useState(null);
  const [filteredData, setData] = useState(props.cardsToShow);

  const handleSort = clickedColumn => {
    if (column !== clickedColumn) {
      setColumn(clickedColumn);
      setData(_.sortBy(filteredData, [clickedColumn]));
      setDirection("ascending");
      return;
    }

    setData(_.sortBy(filteredData.reverse()));
    direction === "ascending"
      ? setDirection("descending")
      : setDirection("ascending");
  };

  return (
    <>
      <div>
        <Search />
        <h3>Vintage Card Search</h3>
        <Table sortable celled fixed striped>
          <Table.Header>
            <Table.Row>
              <Table.HeaderCell
                sorted={column === "title" ? direction : null}
                onClick={handleSort("title")}
              >
                Card Title
              </Table.HeaderCell>
              <Table.HeaderCell># Bids</Table.HeaderCell>
              <Table.HeaderCell>Watchers</Table.HeaderCell>
              <Table.HeaderCell>Price</Table.HeaderCell>
              <Table.HeaderCell>Time Left</Table.HeaderCell>
            </Table.Row>
          </Table.Header>
          <Table.Body>
            {props.cardsToShow.map(card => (
              <>
                <Table.Row key={card.id}>
                  <Table.Cell>{card.title}</Table.Cell>
                  <Table.Cell>
                    {card.sellingStatus[0].bidCount
                      ? card.sellingStatus[0].bidCount
                      : 0}
                  </Table.Cell>
                  <Table.Cell>
                    {card.listingInfo[0].watchCount
                      ? card.listingInfo[0].watchCount
                      : 0}
                  </Table.Cell>
                  <Table.Cell>
                    $
                    {card.sellingStatus &&
                      card.sellingStatus[0].currentPrice[0]["__value__"]}
                  </Table.Cell>
                  <Table.Cell>
                    <TimeAgo
                      date={new Date(
                        card.listingInfo && card.listingInfo[0].endTime
                      ).toLocaleDateString()}
                    />
                  </Table.Cell>
                </Table.Row>
              </>
            ))}
          </Table.Body>
        </Table>
      </div>
    </>
  );
};

const mapStateToProps = state => {
  return {
    baseball: state.baseball,
    search: state.search,
    cardsToShow: searchCards(state)
  };
};

const mapDispatchToProps = {
  searchChange
};

export default connect(mapStateToProps, mapDispatchToProps)(Cards);
// export default Cards;
Run Code Online (Sandbox Code Playgroud)

Rei*_*iks 5

Yachaka 已经指出了不正确的行,但他们的回答并没有解释问题是什么。

当你在 React 中传递 props with 时prop={expression},括号中的表达式会被评估,就像函数参数在传递时被评估一样。因此,无论何时呈现组件,handleSort("title")都会调用。这个函数会导致 props 被更新,组件被重新渲染,导致循环无限重复。

所以问题是,不是传递一个应该在单击按钮时调用的函数,而是调用该函数(使用handleSort("title")),这会导致undefined,并导致反馈循环。

相反,您应该使用返回函数的表达式。正如 Yachaka 提到的,JavaScript 中最简洁的方法是使用箭头函数() => handleSort("title")。这计算为一个调用handleSort.

  • 谢谢你的超级有用的解释。我很高兴你写了这篇文章,因为我有点不确定原因 (2认同)