![](/img/trans.png)
[英]Redux + Hooks useDispatch() in useEffect calling action twice
[英]How to clean up a Redux "useDispatch" action inside useEffect?
我为此找到了很多示例,但没有一个使用 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)
}
};
};
我像这样在Post.tsx
组件中调用这个动作......
const dispatch = useDispatch();
useEffect(() => {
dispatch(asyncGetPostById(postId));
}, []);
这当然是一个简化版本,但它的想法是一样的。 现在我如何清理useEffect
中这样的调度以避免这个错误......
警告:无法对卸载的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。
这个想法是如何取消对 ComponentWillUnmount 的请求(或者在我的例子中是useEffect
中的清理函数),如果它还没有完成,这样你就不会在后台有陈旧或未解决的请求,这会使你的应用程序变慢。
这是一个非常普遍的问题,很多人都成为受害者,并且有很多解决方案,但不适用于这种特殊情况(使用 dispatch 和 redux)。
有些使用AbortController()
,其他使用axios.CancelToken
但我不确定如何在我的情况下使用它们中的任何一个。
为你的动作创建者试试这个:
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)
}
};
这是一个微妙的变化,但是有了这个动作创建者,你实际上并没有返回任何东西(在 TypeScript 中它会是void
)
使用void
返回,您在动作创建器中的dispatch
调用将直接发送到您的减速器,但在您的组件中将不会返回任何内容,因此您不必清理任何内容。
此外,您应该考虑将dispatch
添加到useEffects
依赖项数组中:
const dispatch = useDispatch();
useEffect(() => {
dispatch(asyncGetPostById(postId));
}, [dispatch]);
您必须在减速器中创建一个清理当前状态的case
。 然后在useEffect
你喜欢那样
React.useEffect(()=> {
dispatch(your_action)
return () => dispatch(clean_data_action)
},[])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.