2017-02-14 81 views
1

我正在使用React,Redux和Redux-Thunk處理項目中的登錄表單。使用Redux-Thunk,我可以調度異步操作,例如將提交的登錄表單傳送到後端,並通過reducer將已驗證的數據恢復到狀態。一旦組件獲得了所需的數據,它就可以重定向到它所需的頁面,而不會出現問題。React組件中的異步操作

問題是,在重定向用戶之前,我需要將一些來自異步網絡請求的數據寫入localStorage。如果我不這樣做異步,用戶將被寫入本地存儲的初始狀態值重定向。

作爲解決方案,我在React組件中使用承諾和超時等待傳入數據。

這種方法似乎有效,但它感覺不對,有人可以建議我一個更好的做法嗎?

下面是組件中的代碼,我過濾了大部分不相關的東西,使其儘可能短。

import React, {Component} from 'react'; 
import {bindActionCreators} from 'redux'; 
import {browserHistory} from 'react-router'; 
import {reduxForm} from 'redux-form'; 
import {connect} from 'react-redux'; 

import {validate} from './../utils/login/surfaceValidation'; 
import {inputAlerts} from './../utils/login/inputAlerts'; 

import {submitLogin} from './../redux/actions/index'; 

class Form extends Component { 

    componentWillReceiveProps(nextProps) { 
     if(nextProps.loginApproved) { 
      this.handleValidLogin(); 
     } 
    } 

    handleLogin(props) { 
     this.props.submitLogin(props); 
     // submitLogin is async action handled by redux-thunk it returns 
     // this.props.loginApproved and if it's true componentWillReceiveProps 
     // will trigger. 
    } 

    handleValidLogin() { 
     this.writeToStorage() 
     .then(() => { 
      browserHistory.push('/main'); 
     }).catch((err) => { 
      console.log(err); 
     }); 
    } 

    writeToStorage(){ 
     return new Promise((resolve, reject) => { 
      setTimeout(() =>{ 
       localStorage.setItem('user', 
        JSON.stringify({ 
         authenticated: true, 
         username: this.props.username, 
         id: this.props.id, 
         token: this.props.token 
        })); 
      }, 3000); 
      setTimeout(() => { 
       if(this.props.token != null) { 
        resolve(); 
        console.log('got a token - resolving.'); 
       } else { 
        reject(); 
        console.log('no token - rejecting. '); 
       } 
      }, 4000); 
     }); 
    } 

    render() { 

     return (
      // Login form component is here. 
      // When user submits form, this.handleLogin() is called. 
     ); 
    } 
} 


function mapDispatchToProps(dispatch){ 
    return bindActionCreators({submitLogin}); 
} 

function mapStateToProps(state) { 
    return { 
     loginApproved: state.login.loginApproved, 
     username: state.login.username, 
     id: state.login.id, 
     token: state.login.token 
    }; 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Form); 

回答

1

據我所知localStorage.seItem是同步的,所以你可以重定向之前調用函數將數據保存到存儲。

+0

問題是,將要寫入的值在初始狀態中定義爲null。如果我不使用承諾,或者甚至超時,那麼初始狀態值會在重定向之前寫入。 (將此添加到問題中。) – cinnaroll45

+2

聽起來像您過早調用'handleValidLogin'。只要在你需要的所有道具都到達之前不要調用'handleValidLogin'。例如'if(nextProps.token && nextProps.username && nextProps.id){this.handleValidLogin(); }' – Brandon

+0

這聽起來不錯@Brandon,我會給它一個鏡頭。 – cinnaroll45