2017-02-14 18 views
1

私はReact、Redux、Redux-Thunkのプロジェクトでログインフォームを作成しています。 Redux-Thunkを使用して、提出されたログインフォームをバックエンドに配信し、検証済みのデータをレデューサー経由で元の状態に戻すなどの非同期アクションをディスパッチできます。コンポーネントが必要なデータを取得すると、問題なく必要なページにリダイレクトできます。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

問題は、書き込まれる値が初期状態ではヌルとして定義されていることです。私が約束やタイムアウトを使用しないと、リダイレクトの前に初期状態値が書き込まれます。 (これを質問に追加する) – cinnaroll45

+2

あなたは 'handleValidLogin'を早く呼び出すように聞こえます。必要なすべての小道具が到着するまで、 'handleValidLogin'を呼び出さないでください。例えば'if(nextProps.token && nextProps.username && nextProps.id){this.handleValidLogin(); } ' – Brandon

+0

それは正しい@ブラッドン、私はそれを打つつもりです。 – cinnaroll45

関連する問題