Reputation: 3084
In my React/Redux application, I have some async actions.
Let's say a user initiates a getData
request to the server. Immediately a GET_DATA_REQUEST
is being dispatched and the getData
AJAX call is on its way to the server.
Upon success or failure, a GET_DATA_SUCCESS
or GET_DATA_FAILURE
actions are dispatched accordingly and the data is rendered to the UI.
Now, I want my application to push history state (using react-router-redux
) as a reaction to the AJAX callback. Meaning, upon success, the users is "redirected" to another URL (route) the displays a different module that depends on the newly received data.
I realize it's a very bad idea to have this functionality in the reducer, as it won't be pure anymore (URL change is a side effect).
Any thoughts?
Thanks
Upvotes: 2
Views: 7713
Reputation: 71
Another great way to do this. I learned this from this Udemy course, and I 100% recommend it.
Inside the component (a form you want to submit), put this form submit event handler, which will invoke the action.
submit(values) {
this.props.xxxActionCreator(() => {
this.props.history.push("/");//history is provided by react-route, .push("/") will direct app back to root path.
});
}
render() {
<form onSubmit={this.submit.bind(this)} >
.... </form>
Inside the action creator, put this
export default function xxxAction(callback) {
const request = axios.get('...url').then(() => callback()); //here the function (callback) that was passed into this.props.xxxActionCreator() will be invoked.
//.then() is provided by promise. This line of code means the callback (which redirects you to the root path) will be invoked, once the promise (async) is resolved.
return { type: SOME_ACTION, payload: XXX };
GitHub demo here you can find the relevant code and the whole project. Which is kindly presented by Stephen Grider, a great teacher!
This is one way that doesn't put redirect into the state tree.
Upvotes: 7
Reputation: 28397
I believe this is a good way to handle your situation.
First of all, you should add a new property in your reducer to know if you want to redirect or not.
Something like this
const initialState = {
...
redirect : false // You could use a String with the new url instead of true/false
....
}
switch ...
case GET_DATA_SUCCESS:
return {
...state,
redirect:true,
}
case GET_DATA_FAILURE;
return {
...state,
redirect:false
}
Then, in the component connected to your reducer, you should check the value of "redirect" in the componentDidUpdate function.
componentDidUpdate(){
let {redirect} = this.props.yourReducerState;
if(redirect === true){
this.context.router.push("new-url");
}
}
Finally, you should reset "redirect" on componentWillUnmount
Hope it helps!
Upvotes: 9