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) { // Wait for user to submit the form const data = yield take(ActionTypes.SEND_DATA_REQUEST); let response; try { // Send the data to the server and get a response back response = yield call(apiPost, '/api/data', data); } catch (err) { // Report errors to our store yield put(sendDataFailure(err)); continue; } // Report success to our store and redirect to another page yield put(sendDataSuccess(response)); yield put(push('/next-page')); }}