简体   繁体   English

如何清理 useEffect 中的 Redux“useDispatch”动作?

[英]How to clean up a Redux "useDispatch" action inside useEffect?

I found a lot of examples for this, but none uses Redux and useDispatch , so here's the situation ...我为此找到了很多示例,但没有一个使用 Redux 和useDispatch ,所以情况如下......

I have an action file with an async action like this ...我有一个像这样的异步动作的动作文件......

//postsActions.tsx

export const asyncGetPostById = (postId: string) => {
    return async (dispatch: any, getState: () => AppState) => {
        try {
            dispatch(startLoader());
            const { data } = await axios.get(`api/posts/${postId}`);
            dispatch(setPostDataInReducer(data));
        } catch (error) {
            console.log(error)
        }
    };
};

And I'm calling this action inside the Post.tsx component like this ...我像这样在Post.tsx组件中调用这个动作......

const dispatch = useDispatch();

useEffect(() => {
    dispatch(asyncGetPostById(postId));
}, []);

This is of course a simplified version, but it's the same idea.这当然是一个简化版本,但它的想法是一样的。 Now how can I clean up a dispatch like that in useEffect to avoid this error ...现在我如何清理useEffect中这样的调度以避免这个错误......

Warning: Can't perform a React state update on an unmounted component.警告:无法对卸载的组件执行 React 状态更新。 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 function.要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。

Edit编辑

The idea is how to cancel the request on ComponentWillUnmount (or the cleanup function in useEffect in my case) if it's not done already so that you won't have stale or unresolved requests in the background that will make your app slow.这个想法是如何取消对 ComponentWillUnmount 的请求(或者在我的例子中是useEffect中的清理函数),如果它还没有完成,这样你就不会在后台有陈旧或未解决的请求,这会使你的应用程序变慢。

It's a very common issue that a lot of people fall a victim to, and there's a lot of solutions out there, but not for this particular case (with dispatch and redux).这是一个非常普遍的问题,很多人都成为受害者,并且有很多解决方案,但不适用于这种特殊情况(使用 dispatch 和 redux)。

Some uses AbortController() , and others use axios.CancelToken but I'm not sure how to use either of them in my case.有些使用AbortController() ,其他使用axios.CancelToken但我不确定如何在我的情况下使用它们中的任何一个。

Try this for your action creator:为你的动作创建者试试这个:

export const asyncGetPostById = (postId: string) => async (dispatch: Function, getState: () => AppState) => {
    try {
        dispatch(startLoader());
        const { data } = await axios.get(`api/posts/${postId}`);
        dispatch(setPostDataInReducer(data));
    } catch (error) {
        console.log(error)
    }
};

It's a subtle change, but with this action creator you're not actually returning anything (In TypeScript it would be void )这是一个微妙的变化,但是有了这个动作创建者,你实际上并没有返回任何东西(在 TypeScript 中它会是void

With a void return, your dispatch calls in the action creator will go straight to your reducer, but in your component nothing will be returned, so you shouldn't have to cleanup anything.使用void返回,您在动作创建器中的dispatch调用将直接发送到您的减速器,但在您的组件中将不会返回任何内容,因此您不必清理任何内容。

Edit:编辑:

Additionally, you should consider adding dispatch to your useEffects dependency array:此外,您应该考虑将dispatch添加到useEffects依赖项数组中:

const dispatch = useDispatch();

useEffect(() => {
    dispatch(asyncGetPostById(postId));
}, [dispatch]);

You must to create in your reducer a case that clean the current state.您必须在减速器中创建一个清理当前状态的case And then in useEffect you do like that然后在useEffect你喜欢那样

React.useEffect(()=> {
 dispatch(your_action)
 return () => dispatch(clean_data_action)
},[])
 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM