2017-12-18 156 views
0

背景:
我正在创建一个Login组件。REDO传奇和history.push

saga.js由3个函数组成
1. rootSaga。它将执行sagas的列表
内部的watchSubmitBtn。它会观察提交按钮上的点击并发出一个动作。
3. shootApiTokenAuth将收到出动action和处理axios.post返回值是promise对象

在行动:
后端返回400React。这种情况下没有问题,我可以轻松读取​​并在render()中显示。但是,当返回200。 我需要让用户转到网址/companies

尝试:
我曾试图把this.props.history.push('/companies');componentWillUpdate(),但它不工作。我必须点击Submit 2次才能让React了解token已保存。

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

问题:
我如何设置组件的状态,并push到URL /companies?后端返回200

+0

我读过https://stackoverflow.com/questions/42893161/how-to-provide-a-history-instance-to-a-saga但不明白 – Sarit

回答

1

我通常会处理像saga这样的条件导航。

与现有的代码最简单的答案是通过一个历史记录对象作为SUBMIT_USERNAME_PASSWORD动作的道具,做history.push()调用在传奇的成功案例,是这样的:

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

我只知道我可以通过历史!非常感谢你。我总是以'this'作为前缀的每个属性都无法传递给其他文件。但是我错了。 – Sarit

0

React有额外的生命周期。我今天才知道。他们中的很多人。

componentDidUpdate() { 
    this.props.history.push('/companies'); 
    }