Ключом к тому, чтобы заставить загрузочные функции реагировать на изменения фильтров, является добавление фильтров в список зависимостей useEffect()
.
useEffect(() => {
loadData();
loadStatusList();
}, [filters, pageNumber]);
, хотя я не вижу loadStatusList()
в зависимости от фильтров, поэтому рекомендация состоит в том, чтобы разделить два asyn c вызова на их собственные эффекты
useEffect(() => {
loadData();
}, [filters, pageNumber]);
useEffect(() => {
loadStatusList();
}, []);
Наконец, функции load * воссоздаются при каждом рендеринге, так что вы можете переместить их в соответствующие эффекты или обернуть их в useCallback()
, или переместите их за пределы компонента (но тогда вам придется передавать все параметры вместо использования замыкания).
useEffect(() => {
const loadData = async () => {
...
});
loadData();
}, [filters]);
useEffect(() => {
const loadStatusList = async () => {
...
});
loadStatusList();
}, []);
Я могу видеть из комментариев, что у вас нет подключил события (нажатия кнопок) и изменения состояния.
Побочные эффекты, особенно асинхронные c единицы должны быть завернуты в useEffect()
.
useEffects
срабатывают, когда только состояние изменяется (или особый случай пустого списка зависимостей, который === onMount ).
Так как вы можете запускать эффекты только на т. е. изменение, вы должны заставить событие (нажатие кнопки) изменить какое-либо состояние, а затем использовать это состояние в списке зависимостей useEffect()
в качестве триггера.
Итак, следуя событию onFilterInputChange
onFilterInputChange
-> dispatch(SET_FILTER_INPUT)
-> reducer sets new value for filters
-> effect has filters as dependency, so it runs
-> loadData called with new filters as parameter
-> on response dispatch(FETCH_DATA_SUCCESS) with new data
Единственная проблема, с которой мы можем столкнуться, заключается в том, что pagerNumber
является входом и выходом эффекта, поэтому при обновлении может получить обратную связь l oop.
Чтобы быть в безопасности, мы можем добавить переменную состояния, которая контролирует выборку
const initialState = {
filters: INITIAL_FILTERS,
checks: [],
pagination: INITIAL_PAGINATION,
selectedCheckId: null,
statusList: [],
doFetch: true // initially true === do a fetch on mount
};
const reducer = (state, action) => {
switch (action.type) {
case "FETCH_DATA_PENDING":
return {
...state,
checks: [],
doFetch: true
};
case "FETCH_DATA_SUCCESS":
const { items, pageNumber, pageCount, totalCount } = action.payload;
return {
...state,
checks: items,
pagination: {
...state.pagination,
pageCount,
totalCount,
pageNumber
},
doFetch: false
};
case "FETCH_DATA_ERROR":
return {
...state,
checks: [],
pagination: INITIAL_PAGINATION,
doFetch: false
};
...
const onFilterInputChange = e => {
dispatch({
type: "SET_FILTER_INPUT",
payload: {
[e.target.name]: e.target.value
}
});
dispatch({type: "FETCH_DATA_PENDING" });
};
const onFilterStatusChange = e => {
dispatch({
type: "SET_FILTER_STATE",
payload: {
status
}
});
dispatch({type: "FETCH_DATA_PENDING" });
};
const onFiltersClear = () => {
dispatch({
type: "CLEAR_FILTERS"
});
dispatch({type: "FETCH_DATA_PENDING" });
};
useEffect(() => {
if (doFetch) {
loadData();
}
}, [doFetch]);