Я занимаюсь рефакторингом некоторого кода и превращаю свои компоненты класса в функциональные компоненты, чтобы научиться использовать зацепки и эффекты.Мой код использует 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, потому что названия названы так, чтобы вы знали, в какой компании я работаю.