Очистка предупреждения об эффекте использования с помощью useReducer,

#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.