React Hooks和Redux的重新渲染次数过多

时间:2019-11-23 22:53:33

标签: javascript reactjs react-redux lodash

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

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

它指向此行

setData(_.sortBy(filteredData.reverse()));

这是我的完整组件代码。谁能看到我要做什么的问题?

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;

2 个答案:

答案 0 :(得分:3)

更改此行:

  mRef = mDatabase.getReference("RestaurantUnu").child("Comenzi");

    FirebaseRecyclerOptions<ReceivedCommandsModel> optionsReceivedCommands = new FirebaseRecyclerOptions.Builder<ReceivedCommandsModel>()
            .setQuery(mRef, ReceivedCommandsModel.class)
            .build();


    adapterReceivedCommands = new FirebaseRecyclerAdapter<ReceivedCommandsModel, ReceivedCommandsViewHolder>(optionsReceivedCommands) {

        @NonNull
        @Override
        public ReceivedCommandsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_command,parent,false);
            layoutManagerOrder = new GridLayoutManager(parent.getContext(),3);
            orderRecycler = (RecyclerView) itemView.findViewById(R.id.order_recycler);
            orderRecycler.setLayoutManager(layoutManagerOrder);
            fragmentItem = (LinearLayout)itemView.findViewById(R.id.item_layout);
            return new ReceivedCommandsViewHolder(itemView);


        }

        @Override
        protected void onBindViewHolder(@NonNull final ReceivedCommandsViewHolder receivedCommandsViewHolder, int i, @NonNull final ReceivedCommandsModel receivedCommandsModel) {


            receivedCommandsViewHolder.tableNmb.setText(receivedCommandsModel.getMasa());


            final FirebaseRecyclerOptions<Comanda> optionsOrderModel = new FirebaseRecyclerOptions.Builder<Comanda>()
                    .setQuery(mRef, Comanda.class)
                    .build();


            adapterOrder = new FirebaseRecyclerAdapter<Comanda, OrderViewHolder>(optionsOrderModel) {

                @NonNull
                @Override
                public OrderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                    View itemView = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.item_order,parent,false);

                    //fragmentItem = (LinearLayout)itemView.findViewById(R.id.item_layout);
                    return new OrderViewHolder(itemView);


                }

                @Override
                protected void onBindViewHolder(@NonNull final OrderViewHolder orderViewHolder, int i, @NonNull final Comanda orderModel) {

                   for(OrderModel order : orderModel.getcomanda()){
                    orderViewHolder.comandaTxt.setText(order.getdenumireProdus());}
                }
            };
            adapterOrder.startListening();
            orderRecycler.setAdapter(adapterOrder);
        }
    };

    adapterReceivedCommands.startListening();
    receivedCommandsRecycler.setAdapter(adapterReceivedCommands);

作者

add_filter( 'gravityflow_assignee_field_users', 'sh_gravityflow_assignee_field_users', 10, 3 );
function sh_gravityflow_assignee_field_users( $users, $form_id, $field ) {
$current_user = wp_get_current_user();
$users = array( 
    array( 'value' => 'user_id|'.$current_user->ID, 'text' => $current_user->display_name),
    array( 'value' => 'user_id|2', 'text' => 'Joe' ),
    array( 'value' => 'user_id|3', 'text' => 'Jane' ),
);
if ($users == jerry) {
return 400;
if ($users == Mary) {
return 600;
if ($users == Donald) {
return 340;

编辑:Reinis在下面写了一个很好的解释!

答案 1 :(得分:3)

Yachaka已经指出了错误的答案,但是他们的回答并未说明问题所在。

当您在React中使用prop={expression}传递props时,括号中的表达式将被求值,就像传递函数参数时一样。因此,无论何时呈现组件,都将调用handleSort("title")。然后,此功能将导致道具更新,并重新渲染组件,从而导致循环无限重复。

因此,问题在于,没有传递单击按钮时应调用的函数,而是调用了该函数(使用handleSort("title")),结果为undefined,并引起反馈循环。

您应该使用返回函数的表达式。正如Yachaka提到的() => handleSort("title")一样,JavaScript中最简洁的方法是箭头功能。这将得出一个调用handleSort的函数。