Having react & redux application that using asynchronous calls via Axios, I need to cancel such request that are still in progress once the user navigate to other page or anything else. Being new to react I came up with an idea to keep the axios cancelToken in redux state and cancel it in componentWillUnmount() of the react component.
example:
componentWillUnmount() {
const (isLoading, cancelToken} = this.props;
if (isLoading) {
cancelToken.cancel("Abort request");
}
}
Are there better patterns or solution to this?
EDIT:
Async call is being fired in redux-thunk i.e. action
It depends on where you have implemented your fetch.
If you have placed it within your component, you can fire the cancel event in the componentWillUnmount method.
If you have placed it in a middleware such as redux-saga, you can create and use the cancel token then and there itself.
If it is within an action creator you can try the method suggested here
Related
I have a fairly standard React Native functional component that uses a selector to retrieve a view model from my Redux store(Using redux-observable for async actions), and render it on changes, pseudo code below.
I'm implementing deeplinking, and my problem is that the store code works (I parse the URL and dispatch actions to my Redux store depending on route, navigate to the page, and the data should show) but it does not seem to re-render after an asynchronous action.
From what I can see, the action is dispatching in the background, it makes the async call, dispatches a success action and the store is updated successfully, the component simply does not re-render.
Any ideas? It seems to be an issue with the useSelector hook not firing, on that specific component that is loaded, as navigating away and using other pages works fine.
The user flow is:
User presses a notification which contains a deeplink
This navigates to a specific page
Data is loaded in the background
Upon successful fetch, the page should re-render
function MyPage() {
const dispatch = useDispatch();
const vm = useSelector(selectMyPageVM);
return (<View><Text>{vm.someProp}</Text></View>);
}
I want to cancel some functions after component unmount because it causes memory leak my code looks like this
componentDidUpdate(prevProps) {
if (prevProps.org.org !== this.props.org.org && this.mounted) {
this.props.clearGraph();
this.props.graphGet(this.props.org.org);
this.setState({ org: this.props.org.org });
}
}
componentDidMount() {
const abox = "a" + this.props.org.org.substr("1");
this.props.getHistory(abox);
this.props.graphGet(this.props.org.org);
}
componentWillUnmount() {
}
all I want is to cancel graphGet which is a redux action
You cannot cancel Redux actions by design. Once they get dispatched, they are processed by reducers and the state transition is performed.
You can however dispatch another action to revert the state changes or causing side effects. Normally you would use another library like redux-observable for the latter.
You can for example define 3 actions: START_GRAPH_GET, CANCEL_GRAPH_GET and FINISH_GRAPH_GET. On START you start your fetch, on CANCEL you cancel any outstanding fetches and once a fetch completes you dispatch FINISH and keep the result in the store.
In order to render the results you would need to use react-redux connect with a mapStateToProps function.
To cancel on unmount, you would just dispatch an CANCEL action, if necessary.
Since your code does not show anything related to Redux at all, I think a more general answer is reasonable here.
I'm building a react native app with react navigation, which means I can't pass down props to my components the usual way (they are all nested inside a <Stack.Screen> component from react navigation).
Instead, I'm using the react Context API to pass data down through my component tree.
My problem is that everytime I use dispatch, it seems to act asynchronously. If I do:
const Submit = function () {
//this line is caught by my reducer and the signUpData is added to the state
dispatch({ type: "signUp", signUpData})
axios({ url:'myapiURL', data: state.signUpData, method: "POST" })
}
My post request will be sent with undefined instead of the proper signUpData. Whatever I try to do immediately after a dispatch, it is as if the state has not been updated yet, because dispatch is async.
The problem is that dispatch is not supposed to be async (as far as i understand ? the docs are unclear) and because it doesn't return a promise, I can't use .then() or await/async to make sure the dispatch is complete before my axios or console log happens on the next line.
How do I execute custom callback that is passed into an action through react comp, immediately after redux store update.
The idea is say, I trigger an action from react, which will make network request via thunk and dispatches the action with data. This will lead to reducer updating the store. Now, immediately after this I want to redirect to a different page (history.push()) which is a callback.
Using saga middleware it is much easier, but how to implement similar functly using thunk.
You can pass your callback defined in your component the redirect to different page to the thunk and call that after store update is complete. Like this:
function someThunkAction(callback) {
return (dispatch, getState) => {
// Update store logic...
// After update
callback();
};
}
I want to cancel some functions after component unmount because it causes memory leak my code looks like this
componentDidUpdate(prevProps) {
if (prevProps.org.org !== this.props.org.org && this.mounted) {
this.props.clearGraph();
this.props.graphGet(this.props.org.org);
this.setState({ org: this.props.org.org });
}
}
componentDidMount() {
const abox = "a" + this.props.org.org.substr("1");
this.props.getHistory(abox);
this.props.graphGet(this.props.org.org);
}
componentWillUnmount() {
}
all I want is to cancel graphGet which is a redux action
You cannot cancel Redux actions by design. Once they get dispatched, they are processed by reducers and the state transition is performed.
You can however dispatch another action to revert the state changes or causing side effects. Normally you would use another library like redux-observable for the latter.
You can for example define 3 actions: START_GRAPH_GET, CANCEL_GRAPH_GET and FINISH_GRAPH_GET. On START you start your fetch, on CANCEL you cancel any outstanding fetches and once a fetch completes you dispatch FINISH and keep the result in the store.
In order to render the results you would need to use react-redux connect with a mapStateToProps function.
To cancel on unmount, you would just dispatch an CANCEL action, if necessary.
Since your code does not show anything related to Redux at all, I think a more general answer is reasonable here.