Changing React Route Programmatically with Redux-Saga

Sometimes in a web app you've got a workflow that calls for a route change after a user action. For example, suppose the user has to complete a form and click a button. The data is sent to the server via AJAX and then you'd like to redirect the user to a another page upon successful transmission.

Redux

First, let's set up some action creators

actions.js

export const ActionTypes = { SEND _ DATA _ REQUEST : 'SEND_DATA_REQUEST' , SEND _ DATA _ SUCCESS : 'SEND_DATA_SUCCESS' , SEND _ DATA _ FAILURE : 'SEND_DATA_FAILURE' , }; export const sendDataRequest = details => ({ type : ActionsTypes . SEND _ DATA _ REQUEST , payload : details , }); export const sendDataSuccess = user => ({ type : ActionTypes . SEND _ DATA _ SUCCESS , payload : user , }); export const sendDataFailure = err => ({ type : ActionTypes . SEND _ DATA _ FAILURE , payload : err , error : true , });

Note: The reducer is omitted because it's unnecessary for this example.

React

Your react component looks something like this:

myForm.jsx

import * as React from 'react' ; import { connect } from 'react-redux' ; import { sendDataRequest } from './actions' ; export class MyFormComponent extends React . Component { submitForm = () => { const data = ; this . props . onSubmit ( data ); }; render () { return ( < form onSubmit ={ this . submitForm }> { } </ form > ); } }; const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ onSubmit : data => dispatch ( sendDataRequest ( data )), }); export const MyForm = connect ( mapStateToProps , mapDispatchToProps )( MyFormComponent );

Redux-Saga

React-router-redux exposes action creators, push, replace, go, goForward, and goBack, that perform navigation. We're going to use the push action creator to navigate to a new location.

sendDataSaga.js

import { push } from 'react-router-redux' ; import { apiPost } from './apiClient' ; import { ActionTypes , sendDataSuccess , sendDataFailure } from './actions' ; export function* sendDataSaga () { while ( true ) { const data = yield take ( ActionTypes . SEND _ DATA _ REQUEST ); let response ; try { response = yield call ( apiPost , '/api/data' , data ); } catch ( err ) { yield put ( sendDataFailure ( err )); continue ; } yield put ( sendDataSuccess ( response )); yield put ( push ( '/next-page' )); } }

Further Reading