Бесконечный цикл useEffect при использовании Redux с React Hooks - PullRequest
0 голосов
/ 05 апреля 2019

Я занимаюсь рефакторингом некоторого кода и превращаю свои компоненты класса в функциональные компоненты, чтобы научиться использовать зацепки и эффекты.Мой код использует Redux для управления состоянием и axios для запросов к базе данных с Thunk в качестве промежуточного программного обеспечения для обработки асинхронности.У меня возникла проблема в одном компоненте, который выполняет запрос get для получения списка клиентов, который раньше был componentDidMount.Что бы я ни пытался, функция useEffect попадает в бесконечный цикл и продолжает запрашивать список клиентов.

Компонент CustomersTable, о котором идет речь, получает список клиентов из базы данных и отображает его встол.Компонент оборачивается контейнерным компонентом, который использует соединение Redux для передачи извлеченного списка клиентов в CustomersTable в качестве реквизита.

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

loadCustomers - это действие Redux, которое использует axios дляполучить список клиентов.currentPage, itemsPerPage, sortProp и ascending - это переменные состояния, которые инициализируются в определенные значения в «компонентном монтировании»

Я бы ожидал, что, поскольку я использую пустой массив, он будет выполняться только один раз.Вместо этого он работает непрерывно.Я не могу понять, почему это происходит.Мое лучшее предположение состоит в том, что, когда приставка получает список, она возвращает новый объект для состояния, и поэтому реквизиты меняются каждый раз, что затем вызывает повторную визуализацию, которая затем выбирает новый список.Я использую это неправильно в том, что Redux не предназначен для использования с подобными хуками?

Я закончил работать над этим, добавив следующее:

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

Я неконечно, такое поведение я действительно хочу.Если бы список клиентов был действительно 0, то код продолжал бы получать список.Если бы список был действительно пустым, то я бы хотел, чтобы он получал его только один раз, а затем останавливался.Изменить: Оказывается, это определенно не работает.Это работает для начальной загрузки, но нарушает код для любого удаления или редактирования.

OK, предоставляя больше контекста здесь.Компонент контейнера, который обертывает таблицу 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);

Действие 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()));
  };
}

редуктор для клиентов:

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;
  }
}

I, к сожалению,Я не могу опубликовать большую часть таблицы CustomersTable, потому что названия названы так, чтобы вы знали, в какой компании я работаю.

1 Ответ

1 голос
/ 23 апреля 2019

Итак, если я правильно понимаю ваш код, вы отправляете действие loadCustomers в дочернем компоненте в пределах useEffect, но вы читаете фактические данные у родителей mapStateToProps.

Это, конечно,создать бесконечный цикл как:

  1. родительские чтения customers из магазина (или что-нибудь из магазина, если на то пошло)
  2. рендерит детей
  3. дочерние выборки customers в useEffect
  4. свойствах родительских изменений и причина повторного рендеринга
  5. вся история продолжается вечно

Мораль истории: не dispatch из презентационных компонентов.или, другими словами, dispatch действие из того же компонента, который вы прочитали те же свойства из хранилища.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...