Search code examples
reactjshttp-redirectreduxreact-routerredux-saga

How to redirect after successful saga api call


I'm using React 16

This button

<form onSubmit={this.submitTechnologyHandler}>
    <div className = "row">
        <Button variant="contained" type="submit" >
            Create
        </Button>
    </div>
</form>

calls

submitTechnologyHandler = ( event ) => {
    event.preventDefault();
...
    this.props.onNameChanged(technology);
}

with

const mapDispatchToProps = dispatch => {
    return {
        onNameChanged: (technology) => dispatch(actions.createTechnology(technology))
    };
};

createTechnology is an action creator

export const createTechnology = (technology) => {
    return {
        type: actionTypes.ADD_TECHNOLOGY_START,
        technology: technology
    }
};

This Saga is executed as a result:

export function* newTechnology(action) {
    try{
        const response = yield axios.post("/tech/", action.technology);
        yield console.log("saga/newTechnology", response.data);
        yield put(actions.addTechnology(response.data));

        here I would like to redirect to ('/tech/' + response.data.seoName); if successful
        
    } catch (error) {
        console.log(error)
    }
}

addTechnology updates the store:

export const addTechnology = (technology) => {
    return {
        type: actionTypes.ADD_TECHNOLOGY,
        technology: technology
    }
};

and

const reducer = (state = initialState, action) => {

    switch (action.type) {
        case actionTypes.ADD_TECHNOLOGY:
            return updateObject(state, action.technology);

So How Can I Redirect to a url in Saga or Reducer. Because I get an id from the server and I must use that to redirect?


Solution

  • I fix it using connected-react-router package

    Step 1: Reducer

    src/redux/rootReducer.js
    import {connectRouter} from 'connected-react-router'
    export const rootReducer = history => combineReducers({
       router: connectRouter(history),
       technology: technologyReducer
    });
    

    Step 2: Store

    src/redux/store.js

    import { routerMiddleware } from 'connected-react-router';
    
    export const history = createBrowserHistory({ basename: '/metro' });
    
    const middleware = [
      ...getDefaultMiddleware({
        immutableCheck: false,
        serializableCheck: false,
        thunk: true
      }),
      sagaMiddleware,
      routerMiddleware(history)
    ];
    
    const store = configureStore({
      reducer: rootReducer(history),
      middleware,
      devTools: process.env.NODE_ENV !== "production",
      enhancers: [reduxBatch]
    });
    

    Step 3: Apply ConnectedRouter

    src/app/App.js Replace BrowserRouter with ConnectedRouter

    import {ConnectedRouter} from 'connected-react-router';
    import {history} from '../redux/store'
    <Provider store = {store}>
       <ConnectedRouter history = {history} >
          <PersistGate persistor = {persistor} loading = {<LayoutSplashScreen/>}>
             <React.Suspense fallback = {<LayoutSplashScreen/>}>
                   <MaterialThemeProvider>
                      <I18nProvider>
                         <Routes/>
                      </I18nProvider>
                   </MaterialThemeProvider>
             </React.Suspense>
          </PersistGate>
       </ConnectedRouter>
    </Provider>
    

    Usage

    Saga: src/dev_road/store/sagas/technology.js

    import { push } from 'connected-react-router';
    export function* newTechnology(action) {
       try{
          const response = yield axios.post("/tech/", action.technology);
    
          yield put(actions.addTechnology(response.data));
    
          yield put(push(`/technology/${response.data.seoName}`));
    
       } catch (error) {
          console.log(error)
       }
    }
    

    https://github.com/supasate/connected-react-router/blob/master/FAQ.md#how-to-navigate-with-redux-action