Я создаю пользовательский хук для извлечения api при отправке формы, я делаю вызов api внутри хука useEffect и у меня есть редуктор для обработки состояний хука.
Одно из состояний trigger
вначале установлено в false, что контролирует, если useEffect что-то делает, точка в том, что ловушка возвращает функцию, которая переворачивает значение trigger
, которое вызывает useEffect, только когда вы вызываете эту функцию.
Проблема заключается в том, что функция очистки useEffect вызывается во время вызова API, даже если компонент все еще монтируется.
Функция очистки, похоже, сработала, потому что я установил значение trigger
на основе его предыдущего значения, когда я установил trigger
на фиксированное значение, функция очистки не вызывается, но я теряю свою функциональность
const fetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_TRIGGER':
return {
...state,
trigger: !state.trigger
}
case 'FETCH_INIT':
return {
...state,
isLoading: true,
isError: false
};
case 'FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
datas: action.payload,
};
case 'FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
};
default:
throw new Error();
}
}
const useFetchApi = (query, initialData = []) => {
let isCancelled = false;
const [state, dispatch] = useReducer(fetchReducer, {
isLoading: false,
isError: false,
datas: initialData,
trigger: false
});
const triggerFetch = _ => dispatch({ type: 'FETCH_TRIGGER' });
const cancel = _ => { console.log("canceling");isCancelled = true };
useEffect(_ => {
if (!state.trigger)
return;
triggerFetch();
(async _ => {
dispatch({ type: 'FETCH_INIT' });
try {
const datas = await query();
if (!isCancelled) { //isCancelled is true at this point
dispatch({ type: 'FETCH_SUCCESS', payload: datas })
}
} catch (err) {
if (!isCancelled) {
dispatch({ type: 'FETCH_FAILURE', payload: err })
}
}
})();
return cancel;
}, [state.trigger]);
return { ...state, triggerFetch};
}
Использование:
function MyComponent () {
const { datas, isLoading, isError, triggerFetch } = useFetchApi(query);
return (
<form onSubmit={event => {event.preventDefault(); triggerFetch()}}>
...