为什么 Redux 状态下的 useEffect 会导致无限循环:

Why useEffect in Redux state is causing infinite loop:

我在从 api 获取项目列表时遇到了这个问题。 axios 在操作中发出 get 请求。发送到减速器并改变状态。所以我希望列表仅在用户添加、删除或更新项目时更新。我正在使用 useEffect 挂钩将列表作为依赖项传递给更改,但它只是在无限循环中获取,极大地影响了性能。

动作创作者:

import axios from "axios";
const BASE_URL = "https://localhost:5001/api";

export function getList() {
  return (dispacth) => {
    return axios.get(`${BASE_URL}/billingCycles`).then((res) =>
      dispacth({
        type: "BILLING_CYCLES_FETCHED",
        payload: res.data,
      })
    );
  };
}

减速器:

const INITIAL_STATE = { list: [], billingCycle: {}, credits: [], debts: [] };

// eslint-disable-next-line import/no-anonymous-default-export
export default function (state = INITIAL_STATE, action) {
  switch (action.type) {
    case "BILLING_CYCLES_FETCHED":
      return { ...state, list: action.payload };
  ..MORE CASES BELOW...
  }
}

列表组件:

import React, { useEffect } from "react";

import ListItem from "./ListItem";

import { getList } from "../../store/actions/billingCycleActions";
import { setCreate } from "../../store/actions/modalActions";
import { useDispatch, useSelector } from "react-redux";

function List() {
  const dispatch = useDispatch();
  const billingCycles = useSelector((state) => state.billingCycles.list);

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => dispatch(getList()), [billingCycles]);

  return (
    <div>
      <div className="mb-3 d-flex justify-content-lg-start">
        <button
          className="btn btn-success"
          onClick={() => dispatch(setCreate(true))}
        >
          <i className="fas fa-plus m-1"></i>
          Novo ciclo!
        </button>
      </div>
      <table className="table table-hover border ">
        <thead className="border">
          <tr>
            <th>Nome</th>
            <th>Mês</th>
            <th>Ano</th>
            <th>Ações</th>
          </tr>
        </thead>
        <tbody>
          {billingCycles &&
            billingCycles
              .map((el) => {
                return (
                  <ListItem
                    index={el.id}
                    name={el.name}
                    month={el.month}
                    year={el.year}
                  />
                );
              })
              .reverse()}
        </tbody>
      </table>
    </div>
  );
}

export default List;

这是 Redux 调试工具的图片:

如果您只需要在初始渲染时获取列表,请将依赖项数组留空,这样它只会调用一次

useEffect(() => dispatch(getList()), []);

否则,您的提取将改变 billingCycles,导致 re-render 再次发生,最终导致无限循环。


更多相关信息here