reactjs - 使用 Redux 和 React Hooks 时的无限 useEffect 循环

标签 reactjs redux react-hooks

我正在重构一些代码并将我的类组件转换为函数组件,以此来学习如何使用 Hooks 和 Effects。我的代码使用 Redux 进行状态管理,使用 axios 处理数据库请求,使用 Thunk 作为处理异步的中间件。我在一个组件中遇到问题,该组件执行获取请求以检索过去是 componentDidMount 的客户列表。无论我尝试什么,useEffect 函数都会进入无限循环并继续请求客户列表。

相关组件 CustomersTable 从数据库中获取客户列表并将其显示在表格中。该组件由一个容器组件包装,该容器组件使用 Redux 的 connect 将检索到的客户列表作为 Prop 传递给 CustomersTable

useEffect(() => {
    loadCustomers(currentPage, itemsPerPage, sortProp, (ascending ? 'asc' : 'desc'), {});
  }, []);

loadCustomers is a Redux action that uses axios to fetch the customer list. currentPage, itemsPerPage, sortProp and ascending are state variables that are initialized to specific values on 'component mount'

我希望因为我使用空数组,它只会运行一次。相反,它连续运行。我无法弄清楚为什么会这样。我最好的猜测是,当 redux 获取列表时,它会返回一个新的 state 对象,因此 props 每次都会更改,然后触发重新渲染,然后获取一个新列表。我是不是用错了,因为 Redux 不应该与这样的钩子(Hook)一起使用?

我最终通过添加以下内容来完成这项工作:

useEffect(() => {
    if (!list.length) {
      loadCustomers(currentPage, itemsPerPage, sortProp, (ascending ? 'asc' : 'desc'), {});
    }
  }, []);

我不确定这是我真正想要的行为。如果客户列表确实为 0,那么代码将继续获取该列表。如果列表真的是空的,那么我希望它只获取一次然后停止。编辑:事实证明这绝对行不通。它适用于初始加载,但会破坏任何删除或编辑的代码。

好的,这里提供更多上下文。包装了 CustomersTable 的容器组件是:

import { connect } from 'react-redux';
import loadCustomers from './actions/customersActions';
import { deleteCustomer } from './actions/customerActions';
import CustomersTable from './CustomersTableHooks';

function mapStateToProps(state) {
  return {
    customers: state.customers,
    customer: state.customer
  };
}

export default connect(mapStateToProps, { loadCustomers, deleteCustomer })(CustomersTable);

Action ,loadCustomers 是:

export default function loadCustomers(page = 1, itemsPerPage = 50, sortProp = 'id', sortOrder = 'asc', search = {}) {
  return (dispatch) => {
    dispatch(loadCustomersBegin());
    return loadCustomersApi(page, itemsPerPage, sortProp, sortOrder, search)
      .then(data => dispatch(loadCustomersSuccess(data)))
      .catch(() => dispatch(loadCustomersFailure()));
  };
}

客户的 reducer 是:

export default function customersReducer(state = initialState, action) {
  switch (action.type) {
    case types.LOAD_CUSTOMERS_BEGIN:
      return Object.assign({}, state, { isLoading: true, list: [], totalItems: 0 });
    case types.LOAD_CUSTOMERS_SUCCESS:
      return Object.assign({}, state, { isLoading: false, list: action.customers || [], totalItems: action.totalItems });
    case types.LOAD_CUSTOMERS_FAILURE:
      return Object.assign({}, state, { isLoading: false, list: [], totalItems: 0 });
    default:
      return state;
  }
}

很遗憾,我无法发布太多的 CustomersTable 本身,因为这些内容的命名方式可以告诉您我在为哪家公司工作。

最佳答案

所以,如果我正确理解了您的代码,您将在 useEffect 内的子组件中调度 loadCustomers 操作,但您在 parent mapStateToProps.

当然,这会创建无限循环:

  1. parent 从商店(或商店中的任何东西,就此而言)读取 customers
  2. 渲染 child
  3. child 在 useEffect
  4. 中获取 customers
  5. 父属性改变并导致重新渲染
  6. 整个故事永远持续下去

故事的寓意:不要dispatch 从展示组件。或者,换句话说,dispatch 一个 Action 来自你从 store 中读取相同属性的同一个组件。

关于reactjs - 使用 Redux 和 React Hooks 时的无限 useEffect 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55539299/

相关文章:

javascript - 类型 'typeof C:/Users/pfftd/projectcrystal/src/actions/crystalActions' 的参数不可分配给类型 'ActionCreatorsMapObject' 的参数)

reactjs - 从功能组件外部获取 React Hook Value

reactjs - 多选文件按钮

javascript - 使用钩子(Hook)处理/删除组件

javascript - 如何使用 ReactJs 将 Props() 值传递到 setState() 以使模态表单可编辑

javascript - 如果我在 throw props 中调用函数,useEffect 会显示警告吗?

reactjs - 在 useEffect 中调用 Redux Action

javascript - 如何将组件从数组传递到路由react-router-dom( typescript )

javascript - 完成多次迭代以创建通用过滤器

redux - 我应该将所有组件状态放在商店中吗?