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

Rub*_*uby 8 reactjs redux next.js react-hooks use-effect

我找到了很多这方面的例子,但没有一个使用 Redux 和useDispatch,所以情况如下......

我有一个带有这样的异步操作的操作文件......

//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)
        }
    };
};
Run Code Online (Sandbox Code Playgroud)

我在Post.tsx组件内调用此操作,如下所示......

const dispatch = useDispatch();

useEffect(() => {
    dispatch(asyncGetPostById(postId));
}, []);
Run Code Online (Sandbox Code Playgroud)

这当然是一个简化版本,但想法是一样的。现在我怎样才能清理这样的调度以useEffect避免这个错误......

警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。

编辑

这个想法是如何取消对 ComponentWillUnmount 的请求(或者在useEffect我的例子中是清理函数),如果它还没有完成,这样你就不会在后台有过时的或未解决的请求,这会让你的应用程序变慢。

这是一个非常常见的问题,很多人都成为受害者,并且有很多解决方案,但不适用于这种特殊情况(使用调度和还原)。

有些使用AbortController(),其他使用axios.CancelToken,但我不确定在我的情况下如何使用它们。

ran*_*tao 1

为你的动作创建者尝试一下这个:

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)
    }
};
Run Code Online (Sandbox Code Playgroud)

这是一个微妙的变化,但对于这个动作创建者来说,你实际上并没有返回任何东西(在 TypeScript 中是这样void

通过void返回,您dispatch在操作创建器中的调用将直接进入您的减速器,但在您的组件中不会返回任何内容,因此您不必清理任何内容。

编辑:

此外,您应该考虑添加dispatchuseEffects依赖项数组中:

const dispatch = useDispatch();

useEffect(() => {
    dispatch(asyncGetPostById(postId));
}, [dispatch]);
Run Code Online (Sandbox Code Playgroud)