![](/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.