在React中成功调用动作后如何从组件重定向?

时间:2019-07-20 12:49:07

标签: reactjs

我在redux中的一个动作中调用了API。

export const registerUser = registeredUserData => async dispatch => {
  let messages;
  try {
    const response = await axios.post('/users/register', registeredUserData);
    messages = response.data
  } catch (error) {
    if (error.response) {
      messages = error.response.data
    }
  }

  dispatch({
    type: REGISTER_USER,
    messages,
  });
};

将表格汇总后会调用此操作。

const onRegisterUser = (e) => {
    e.preventDefault();
    registerUser(registeredUserData);
  };

如果通话成功,我想重定向到另一个页面。 我面临的问题是在这种情况下我不知道如何实现history.push()

如果我将其放在registerUser(registeredUserData);之后的组件的方法内部,那么无论调用响应如何,它都会立即被调用。而且我不确定从操作本身重定向是否是个好主意。

所有帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

在您的示例中,您的操作registerUser是一个承诺,因为它是一个async函数。因此,您可以将onRegisterUser改写成这样:

const onRegisterUser = (e) => {
    e.preventDefault();
    registerUser(registeredUserData)
        .then(() => /* success */)
        .catch(error => /* handle my failure */)
};

话虽如此,您可能需要考虑为网络呼叫创建SUCCESSFAILURE操作。这样,您就可以根据注册用户api调用来更新redux的状态。

您可以将thunk修改为如下形式:

export const registerUser = registeredUserData => async dispatch => {
  try {
    const response = await axios.post('/users/register', registeredUserData);
    dispatch({
      type: REGISTER_USER_SUCCESS,
      messages: response.data,
    });
  } catch (error) {
    if (error.response) {
      dispatch({
        type: REGISTER_USER_FAILURE,
        messages: error.response.data,
      });
    }
  }
};

然后您可以使用React生命周期方法之一来检查redux更改中的状态。假设该代码段正在使用react-redux和connect

您可能还想考虑研究action creators

使用React生命周期方法的另一种方法是使用类似redux-saga的东西,它可以发出SUCCESSFAILURE动作的信号,并代表您执行history.push。

您可能还想看看react router,如果您还没有的话。它提供了访问历史记录和管理路由的方法。

在您的示例中,异步/等待的目的是不必使用嵌套的Promise链。

您的try / catch块等效于then / catch。因此,如果您想使用上面的方法并在响应为400时捕获它,您将需要删除try catch并处理onRegisterUser中的错误(不建议),或者您需要重新抛出该错误调用catch时会调用registerUser

这是registerUser上的一个示例,当响应失败时,该示例应返回捕获。

export const registerUser = registeredUserData => async dispatch => {
  try {
    const response = await axios.post('/users/register', registeredUserData);
    await dispatch({
      type: REGISTER_USER,
      messages: response.data,
    });
  } catch (error) {
    if (error.response) {
      await dispatch({
        type: REGISTER_USER,
        messages: error.response.data,
        isError: true,
      });
      throw new Error(error.response.data);
    }
  }
};

您可能想通过装饰错误对象来将throw new Error(error.response.data)替换为更具体的内容。

答案 1 :(得分:0)

您快到了。在您的组件中,将this.props.history作为参数传递给redux操作。从那里,在分派操作后,您可以重定向到其他页面。

附言:从动作本身重定向是一个不错的主意。

在您的组件内部:

const onRegisterUser = (e) => {
    e.preventDefault();
    registerUser(registeredUserData, this.props.history);
  };

内部行动:

export const registerUser = (registeredUserData, history) => async dispatch => {
  let messages;
  try {
    const response = await axios.post('/users/register', registeredUserData);
    messages = response.data
  } catch (error) {
    if (error.response) {
      messages = error.response.data
    }
  }

  dispatch({
    type: REGISTER_USER,
    messages,
  });

    history.push('/redirect-route);
};

答案 2 :(得分:0)

嗨艾伦,

您基本上可以从this.props.history.push中获得Router,并将其传递给应用程序中所有Route子组件。

您可以通过console.log('__props__', this.props)方法中的render对该组件进行确认。

为了实现这一点,我建议将其作为对您的操作registerUser的回调发送,以实现此目的:

  • cb添加到您的操作中:
export const registerUser = registeredUserData => async dispatch => {
  let messages;
  try {
    const response = await axios.post('/users/register', registeredUserData);
    messages = response.data
  } catch (error) {
    if (error.response) {
      messages = error.response.data
    }
  }

  dispatch({
    type: REGISTER_USER,
    messages,
  });

  // maybe you want a conditional redirect?
  if(/*somecondition to check data or error?*/){
    cb && cb(); //if callback exists, invoke it
  }
};
  • 并针对:onRegisterUser
const onRegisterUser = (e) => {
  e.preventDefault();
  registerUser(registeredUserData, () => {
    this.props.history.push(//route);
  });
};

希望能奏效,否则请描述行为。