redux saga和history.push [英] redux saga and history.push

查看:139
本文介绍了redux saga和history.push的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Backgrond:

我正在创建登录组件。

saga.js 由3个函数组成

1. rootSaga 。它将在
内执行 sagas 列表。 watchSubmitBtn 。它会看到提交按钮上的点击并发送一个动作。

3. shootApiTokenAuth 将收到已发送的动作和进程 axios.post 返回值是 promise object

saga.js is composed by 3 functions
1. rootSaga. It will execute the list of sagas inside
2. watchSubmitBtn. It will watch the click on the submit button and dispatch an action.
3. shootApiTokenAuth will receive dispatched action and process axios.post the return value is promise object

在行动中:

后端将 400 返回反应。这种情况没问题我可以阅读有效负载并轻松地在 render()中显示。但是当返回 200 时。
我需要让用户转到网址 / companies

In action:
Backend returns 400 to the React. This case no problem I can read the payload and display in the render() easily. But when 200 is returned. I need to let user go to the url /companies.

尝试:

我曾尝试在 componentWillUpdate中输入 this.props.history.push('/ companies'); (),但它不起作用。我必须单击提交 2次才能让React明白令牌已保存。

Attempt:
I had tried put this.props.history.push('/companies'); in the componentWillUpdate(), but it does not work. I have to click Submit 2 times to get React understand that token has been saved.

Login.js

import React, {Component} from 'react';
import ErrorMessage from "../ErrorMessage";
import {Field, reduxForm} from 'redux-form';
import {connect} from 'react-redux';
import {validate} from '../validate';
import {SUBMIT_USERNAME_PASSWORD} from "../../constants";

class Login extends Component {

  constructor(props) {
    //Login is stateful component, but finally action will change
    //reducer state
    super(props);
    const token = localStorage.getItem('token');
    const isAuthenticated = !((token === undefined) | (token === null));
    this.state = {
      token,
      isAuthenticated,
      message: null,
      statusCode: null
    };
  }

  onSubmit(values) {
    const {userid, password} = values;
    const data = {
      username: userid,
      password
    };
    this.props.onSubmitClick(data);
  }

  componentWillUpdate(){
    console.log('componentWillUpdate');
    if(this.props.isAuthenticated){
      this.props.history.push('/companies');
    }
  }

  renderField(field) {
    const {meta: {touched, error}} = field;
    const className = `'form-group' ${touched && error ? 'has-danger' : ''}`;

    console.log('renderField');

    return (
      <div className={className}>
        <label>{field.label}</label>
        <input
          className="form-control"
          type={field.type}
          placeholder={field.placeholder}
          {...field.input}
        />
        <div className="text-help">
          {touched ? error : ''}
        </div>
      </div>
    );
  }

  render() {
    const {handleSubmit} = this.props;

    return (
      <div>
        <ErrorMessage
          isAuthenticated={this.props.isAuthenticated}
          message={this.props.message}
        />

        <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
          <Field
            name="userid"
            component={this.renderField}
            placeholder="User ID"
            type="text"
          />
          <Field
            name="password"
            component={this.renderField}
            placeholder="Password"
            type="password"
          />
          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
        <a className='btn btn-primary' href="https://www.magicboxasia.com/">Sign up</a>
      </div>
    );
  }
}


const onSubmitClick = ({username, password}) => {
  return {
    type: SUBMIT_USERNAME_PASSWORD,
    payload: {username, password}
  };
};

const mapStateToProps = (state, ownProps) => {
  return {
    ...state.login
  }
};

export default reduxForm({
  validate,
  form: 'LoginForm'
})(
  connect(mapStateToProps, {onSubmitClick})(Login)
);

saga.ja

const shootApiTokenAuth = (values) =>{
  const {username, password} = values;
  return axios.post(`${ROOT_URL}/api-token-auth/`,
    {username, password});
};

function* shootAPI(action){
  try{
    const res = yield call(shootApiTokenAuth, action.payload);
    yield put({
      type: REQUEST_SUCCESS,
      payload: res
    });
  }catch(err){
    yield put({
      type: REQUEST_FAILED,
      payload: err
    });
  }
}

function * watchSubmitBtn(){
  yield takeEvery(SUBMIT_USERNAME_PASSWORD, shootAPI);
}

// single entry point to start all Sagas at once
export default function* rootSaga() {
  yield all([
    watchSubmitBtn()
  ])
}

问题:

如何设置组件状态,推送到url / companies ?在后端返回 200

Problem:
How can I set the component state and push to url /companies? after backend returns 200?

推荐答案

我通常会处理条件导航在传奇中。

I usually handle conditional navigation like that in the saga.

现有代码的最简单答案是在SUBMIT_USERNAME_PASSWORD操作中将历史对象作为prop传递,并在其中执行history.push()调用。传奇的成功案例,如:

The simplest answer with the existing code is to pass a history object as a prop in the SUBMIT_USERNAME_PASSWORD action and do the history.push() call in the success case of the saga, something like:

const onSubmitClick = ({username, password}) => {
  const { history } = this.props;

  return {
    type: SUBMIT_USERNAME_PASSWORD,
    payload: {username, password, history}
  };
};

.......

function* shootAPI(action){
  try{
    const res = yield call(shootApiTokenAuth, action.payload);
    const { history } = action.payload;

    yield put({
      type: REQUEST_SUCCESS,
      payload: res
    });

    history.push('/companies');
  }catch(err){
    yield put({
      type: REQUEST_FAILED,
      payload: err
    });
  }
}

这篇关于redux saga和history.push的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆