#javascript #reactjs
Вопрос:
Я продолжаю получать эти предупреждения:
Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup
Для некоторых из моих эффектов использования, которые извлекают данные из API с помощью моего пользователя:
export default function HomeBucketsExample(props) {
const {mobileView} = props
const [allDemoBuckets, dispatchAllBuckets] = useReducer(reducer, initialStateAllBuckets)
const ListLoading = LoadingComponent(HomeBucketLists);
useEffect(() =>
{
getAllDemoBuckets(dispatchAllBuckets);
}, [])
return (
<ListLoading mobileView={ mobileView} isLoading={allDemoBuckets.loading} buckets={allDemoBuckets.data} />
);
}
Однако я не уверен, как устранить этот эффект выше, я попытался установить его с помощью True
, и False
, однако, ошибка все равно появилась. Как я могу исправить свою функцию выше, чтобы эффект использования не выдавал никаких предупреждений
ИЗМЕНИТЬ: код для моего reduer:
export const getAllDemoBuckets = (dispatch) => axiosInstance
.get('demo/all/')
.then(response => {
dispatch({ type: 'FETCH_SUCCESS', payload: response.data })
console.log('fired bucket-data')
})
.catch(error => {
dispatch({ type: 'FETCH_ERROR' })
})
const initialStateAllBuckets = {
loading: true,
error: '',
data: []
}
const reducer = (state, action) =>
{
switch (action.type)
{
case 'FETCH_SUCCESS':
return {
loading: false,
data: action.payload,
error: ''
}
case 'FETCH_ERROR':
return {
loading: false,
data: {},
error: "Something went wrong!"
}
default:
return state
}
}
const [allDemoBuckets, dispatchAllBuckets] = useReducer(reducer, initialStateAllBuckets)
Комментарии:
1. Добавьте также редуктор, пожалуйста. Эта ошибка появляется, когда вы отключаете компонент до того, как вернется ответ от API, и ваш компонент пытается изменить состояние с помощью этого ответа.
2. Пожалуйста, посмотрите мою новую правку
Ответ №1:
Цель предупреждения состоит в том, чтобы сообщить вам, что после отключения компонента происходит какое-то действие и что результат этой работы будет удален.
Решение состоит не в том, чтобы пытаться обойти это с помощью редуктора; решение состоит в том, чтобы отменить все, что происходит, вернув обратный вызов из useEffect. Например:
useEffect(() => {
const ctrl = new AbortController();
fetchExternalResource(ctrl.signal);
return () => {
ctrl.abort();
}
}, []);
Использование флагов для определения того, установлен ли компонент (т. Е. с помощью редуктора), чтобы определить, отсутствует ли в состоянии обновления точка предупреждения.
Также можно оставить предупреждение включенным, если на самом деле это не проблема. Это просто для того, чтобы придраться и сказать вам, что, эй, возможно, вы захотите все это убрать. Но это не ошибка.
В вашем случае, если вы используете fetch, я бы изменил ваш код таким образом, чтобы функция, отправляющая действия, могла AbortSignal
отменить свои операции. Если вы не используете fetch, вы мало что можете сделать, и вам следует просто игнорировать это предупреждение. В этом нет ничего особенного.
Похоже, вы используете Axios для своих запросов. Axios поддерживает механизм, аналогичный сигналам прерывания, — это должно сработать.
import { CancelToken } from 'axios';
const getAllDemoBuckets = async (dispatch, cancelToken) => {
try {
const response = await axiosInstance.get('/demo/all', { cancelToken });
dispatch({ type: 'FETCH_SUCCESS', payload: response.data });
} catch (err) {
if ('isCancel' in err amp;amp; err.isCancel()) {
return;
}
dispatch({ type: 'FETCH_ERROR' });
}
}
const MyComponent = () => {
useEffect(() => {
const source = CancelToken.source();
getAllDemoBuckets(dispatch, source.token);
return () => {
source.cancel();
};
}, []);
}
Комментарии:
1. Как я могу исправить предупреждение об эффекте использования, которое я получаю, когда использую ваш код? Большое спасибо.
2. Мой ответ объясняет, почему возникает предупреждение и как его избежать — путем отмены операции, вызывающей обновление состояния, путем возврата обратного вызова из useEffect.