I found a lot of examples for this, but none uses Redux and useDispatch
, so here's the situation ...
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 ...
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 ...
Warning: 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 function.
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.
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).
Some uses AbortController()
, and others use axios.CancelToken
but I'm not sure how to use either of them in my case.
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
)
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.
Additionally, you should consider adding dispatch
to your useEffects
dependency array:
const dispatch = useDispatch();
useEffect(() => {
dispatch(asyncGetPostById(postId));
}, [dispatch]);
You must to create in your reducer a case
that clean the current state. And then in useEffect
you do like that
React.useEffect(()=> {
dispatch(your_action)
return () => dispatch(clean_data_action)
},[])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.