成功操作后重定向到特定页面 - Redux saga

Redirect to a specific page after successful action - Redux saga

我有一个用户个人资料页面,用户可以在其中更新数据。提交数据后,应将其重定向到仪表板页面。

MyProfile.js

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

动作定义如下

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

Saga文件定义如下。

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()
  ]);
}

但是代码 yield put(push('/dashboard')) 没有重定向到页面。

知道如何解决这个问题吗?

我自己创建了一个解决方案

history.js

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

将历史文件导入 saga

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

修改watcher saga如下。

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);
  }
}

现在,您需要按如下方式定义 forwardTo 函数。

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

您需要将历史对象推送到不同的路径。

  1. 如果你可以在你的动作中传递历史对象,你可以直接 写 history.push('/dashboard').
  2. 你传入一个回调函数 调用操作的操作并调用该回调 使用 yield put(callback()) 函数,以便您可以重定向 使用第 1 点中提到的相同命令。
  3. window.location.href = 'dashboard';

这是我一直在做的事情的一个简单示例,也是我发现使它起作用的唯一方法:(带 sagas 的打字稿)

MyCreateUserComponent.tsx

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

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

  // call Actioncreator
  DeleteUser(userId, meta)
}

actioncreator DeleteUser 看起来像这样:

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

关于我的故事...我做了删除用户所需的操作(调用 api、bla、bla),然后我调用:

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

整个想法就是将推送功能与其余数据一起传递,并在需要时使用它。

这是我所做的并且有效(接受的答案对我不起作用):

在你的减速器中,你添加了一个布尔变量来指示你的请求是否成功。所以你有如下内容:

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

userProfileUpdated明显是初始化为false.

现在,在您的组件中,您执行如下操作:

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

一旦您的用户配置文件已成功更新,您的 userProfileUpdated 变量将切换为 true,并且您的 MyProfile 组件将 re-render 加载您的 Redirect 组件您将使用 /dashboard 作为路径名从 react-router-dom 导入。