简体   繁体   中英

Redirect to a specific page after successful action - Redux saga

I have a user profile page where the user can update the data. Once the data is submitted, it should be redirected to dashboard page.

MyProfile.js

  handleProfileUpdate = () => {
    let user = this.state;
    this.props.updateUserProfile(user);
  }

Action is defined as follows

export const updateUserProfile = (obj) => ({
  type: types.USER_PROFILE_UPDATE_REQUEST,
  payload: obj
});

Saga file is defined as follows.

function* updateUserProfile(action) {
  try {
    let data = action.payload;
    yield call(userProvider.updateUserProfile, data);

    // dispatch a success action to the store
    yield put({ type: types.USER_PROFILE_UPDATE_SUCCESS, data });
    yield put(push('/dashboard'));
    yield put(constants.successMsg(userProfileUpdateSuccess));

  } catch (error) {
    // dispatch a failure action to the store with the error
    yield put(constants.DEFAULT_ERROR_MSG);
  }
}

export function* watchUserProfileUpdateRequest() {
  yield takeLatest(types.USER_PROFILE_UPDATE_REQUEST, updateUserProfile);
}


export default function* userSaga() {
  yield all([
    watchUserProfileRequest(),
    watchUserProfileUpdateRequest()
  ]);
}

But the code yield put(push('/dashboard')) is not redirecting on to the page.

Any idea on how to fix this?

I founded a solution myself

history.js

import createHistory from 'history/createBrowserHistory';
const history = createHistory();
export default history;

Import history file into the saga

import history from '../../history';

Modify the watcher saga as follows.

function* updateUserProfile(action) {
  try {
    let data = action.payload;
    yield call(userProvider.updateUserProfile, data);

    // dispatch a success action to the store
    yield put({ type: types.USER_PROFILE_UPDATE_SUCCESS, data });
    yield call(forwardTo, '/dashboard');
    yield put(constants.successMsg(userProfileUpdateSuccess));

  } catch (error) {
    // dispatch a failure action to the store with the error
    yield put(constants.DEFAULT_ERROR_MSG);
  }
}

Now, you need to define the forwardTo function as follows.

function forwardTo(location) {
  history.push(location);
}

This is a simple example of what I've been doing, and the only way I found to make this work: (typescript with sagas)

MyCreateUserComponent.tsx

onHandleDelete() {
  const { push } = this.props.history

  const meta: ISagaActionMeta = {
    redirect: push,
    path: '/users'
  }

  // call Actioncreator
  DeleteUser(userId, meta)
}

actioncreator DeleteUser looks something like this:

export const DeleteUser = (userId: number, meta: ISagaActionMeta): ISagaAction<number> => {
  return {
    type: Actions.user.USER_DELETE,
    payload: userId,
    meta
  }
}

on my saga... I do what its needed to delete the user (call the api, bla, bla) and then I call:

yield call(action.meta.redirect, action.meta.path)

The entire idea is just to pass the push function together with the rest of the data and use it when needed it.

You need the history object to push to a different path.

  1. If you can pass the history object in your action you can directly write history.push('/dashboard') .
  2. You pass a callback function in the action from where the action was called and call that callback function with yield put(callback()) so that you can redirect with the same command as mentioned in point 1.
  3. window.location.href = 'dashboard';

Here's what I did and which works (The accepted answer just does not work for me):

In your reducer, you add a boolean variable that will indicate if your request is a success. So you have something as follows:

case USER_PROFILE_UPDATE_SUCCESS:
    return {
      ...state,
      userProfileUpdated: true
    } 
  };

userProfileUpdated is obviously initiated to false.

Now, in your component, you do something as follows:

   render() {
      const { myReducer } = this.props;
        if (myReducer.userProfileUpdated) {
          return this.renderRedirect(ROUTES.DASHBOARD);
        } else {
          return this.renderUserProfileComponent();
        }
    }

Once your user profile has been successfully updated, your userProfileUpdated variable will switch to true, and your MyProfile component will re-render to load your Redirect component which you will have imported from react-router-dom with /dashboard as a pathname.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM