2017-12-18 153 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'); 
    }