使用 useReducer 清除 useEffect 警告,

时间:2021-04-16 18:34:21

标签: 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

对于我在 useReducer 的帮助下从 API 中提取数据的一些 useEffects:

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} />
    );
}

但是,我不确定如何清除上面的这种效果,我尝试使用 TrueFalse 安装它,但是错误仍然出现。如何修复上面的函数,以便 useEffect 不会抛出任何警告

编辑: 我的 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 个答案:

答案 0 :(得分: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 && err.isCancel()) {
      return;
    }

    dispatch({ type: 'FETCH_ERROR' });
  }
}

const MyComponent = () => {
  useEffect(() => {
    const source = CancelToken.source();
    getAllDemoBuckets(dispatch, source.token);
    return () => {
      source.cancel();
    };
  }, []);
}
相关问题