2017-10-08 186 views
0

我已經創建了一個部署在Heroku上的rails API,並且我想使用reactJS和redux來編寫前端代碼,以瞭解此框架。現在,我有一個登錄頁面和一個註冊頁面。註冊頁面沒有使用redux(現在),登錄頁面使用redux。當用戶登錄時,存儲在sessionStorage中的令牌,但我不明白我如何訪問用戶數據(如用戶名,電子郵件等)。React Redux - 登錄後獲取用戶和授權令牌

當用戶登錄後,他被重定向到/ dashboard /:id頁面,我想用這個:id做一個API調用,但我不想使用url參數來做到這一點,我想在我的登錄組件和儀表板組件之間傳遞狀態/道具。我不知道如何使用react/redux來做到這一點。

這裏是登錄表單代碼:

import React, { Component } from 'react'; 
import { Link, Redirect } from 'react-router-dom'; 
import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 
import * as authActions from '../../actions/authActions'; 
import axios from 'axios'; 


class LoginForm extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      email: '', 
      password: '', 
      errors: {}, 
      isLoading: false, 
     }; 
    } 

    onChange(e) { 
     this.setState({ 
      [e.target.name]: e.target.value 
     }) 
    } 

    onSubmit(e) { 
     e.preventDefault(); 
     this.setState({ errors: {}, isLoading: true }); 
     this.props.actions.logInUser({ data: { user: { email: this.state.email, password: this.state.password }}}) 
    } 

    render() { 
     return(
      <div> 
       <form onSubmit={this.onSubmit.bind(this)}> 
        <div className="field"> 
         <label className="label"> Email </label> 
         <div className="control"> 
          <input type="email" 
            name="email" 
            value={this.state.email} 
            onChange={this.onChange.bind(this)} 
            className="input" /> 
         </div> 
        </div> 
        <div className="field"> 
         <label className="label"> Mot de passe </label> 
         <div className="control"> 
         <input type="password" 
           ref="password" 
           name="password" 
           value={this.state.password} 
           onChange={this.onChange.bind(this)} 
           className="input" /> 
         </div> 
        </div> 
        <div className="form-group"> 
         <input type="submit" value="Signup" className="button is-primary" /> 
        </div> 
        <Link to={{ pathname: '/register' }}>Inscription</Link> 
       </form> 
      </div> 
     ); 
    } 
} 

function mapDispatchToProps(dispatch) { 
    return { 
     actions: bindActionCreators(authActions, dispatch) 
    }; 
} 

export default connect(null, mapDispatchToProps)(LoginForm); 

這裏是authActions代碼:

import axios from 'axios'; 
import setAuthorizationToken from '../utils/setAuthorizationToken'; 
import jwtDecode from 'jwt-decode'; 
import { browserHistory } from 'react-router'; 
import * as types from './types'; 
import sessionApi from '../api/SessionApi'; 

export function loginSuccess() { 
    return { 
     type: types.LOG_IN_SUCCESS 
    } 
} 


export function loginFailed() { 
    return { 
     type: types.LOG_IN_FAILED 
    } 
} 

export function logInUser(credentials) { 
    return function(dispatch) { 
     return sessionApi.login(credentials) 
      .then(response => { 
       console.log(response); 
       if(response.data) { 
        sessionStorage.setItem('jwt', response.data.authentication_token); 
        dispatch(loginSuccess()); 
        browserHistory.push('/dashboard/' + response.data.id); 
       } else { 
        dispatch(loginFailed()); 
       } 
      }) 
      .catch(error => { 
       throw(error); 
      }) 
    } 
} 

儀表板組件代碼現在:

import React, { Component } from 'react'; 
import axios from 'axios'; 
import * as authActions from '../../actions/authActions'; 

class Dashboard extends Component { 
    constructor(props) { 
     super(props); 
    } 

    render() { 
     return(
      <div> 
       <h1> Hello user </h1> 
      </div> 
     ); 
    } 
} 

export default Dashboard; 

的會議減速器代碼:

import * as types from '../actions/types'; 
import initialState from './initialState'; 
import { browserHistory } from 'react-router'; 

export default function sessionReducer(state = initialState.session, action) { 
    switch(action.type) { 
     case types.LOG_IN_SUCCESS: 
      return !!sessionStorage.jwt; 
     case types.LOG_IN_FAILED: 
      console.log('login failed'); 
      browserHistory.push('/login'); 
     default: 
      return state; 
    } 
} 

,並與API調用sessionApi:

import axios from 'axios'; 
class SessionApi { 
    static login(credentials) { 
     return axios.post('https://spendin-api.herokuapp.com/api/v1/sessions', credentials) 
     .then(response => { 
      console.log(response); 
      return response; 
     }) 
     .catch(error => { 
      return error; 
     });    
    } 
} 

export default SessionApi; 

我想,當我做的API調用,如用戶名,ID通過,我接收到的數據,以及更多......

謝謝!

編輯

的rootReducer:

import { combineReducers } from 'redux'; 
import session from './sessionReducer'; 

const rootReducer = combineReducers({ 
    session, 
}); 

export default rootReducer; 

回答

1

loginSuccess取一個數據對象參數:

export function loginSuccess(userData) { 
return { 
    type: types.LOG_IN_SUCCESS, 
    payload: userData 
    } 
} 

當你發送的行動,在數據傳遞從您的API調用。請注意,這是假定你的API返回的JSON有效載荷的用戶數據對象,所以你需要修改,以符合你的API返回:

if(response.data) { 
       sessionStorage.setItem('jwt', response.data.authentication_token); 
       dispatch(loginSuccess(response.data.userData)); 

然後在你的減速,將數據放到了Redux店:

case types.LOG_IN_SUCCESS: 
    return { 
     ...state, 
     userData: action.payload 
    }; 

順便說一句,你的減速機看起來不正確。兩件事情,我建議:

  1. 不要做的副作用任何東西(例如導航到另一個頁面!)在減速的代碼。這肯定會導致意想不到的行爲和錯誤。改爲在動作創建者身上做任何有副作用的事情。

  2. 修改reducer中的狀態時,總是返回已傳入的狀態的修改版本。使用reducer返回布爾值不是Redux模式;雖然它可能工作,如果你的reducer只有一個值,它會混淆任何習慣於閱讀Redux代碼的人。顯然上面的變化你的狀態將不再包含一個單一的布爾值。

要訪問儀表板組件中的用戶數據,請將其打包到connect()的調用中。你的新的出口將是這個樣子:

function mapStateToProps(state) { 
     const userData = state.sessionReducer.userData; 
     return { userData }; 
    } 

    export default connect(mapStateToProps)(Dashboard); 

這裏假設你有,你有combineReducers結合多個減速。您的儀表板組件將收到一個userData道具。

+0

謝謝你的答案,我有一個結合reducer的rootReducer(代碼在我編輯的問題中),我是否需要在儀表板組件中導入sessionReducer?因爲我有一個錯誤「無法讀取未定義的屬性userData」 –

+0

不,您永遠不會將縮減器導入視圖組件。它不會連接到商店,所以它的狀態將始終爲空/默認狀態。這可能不起作用,因爲您在combineReducers中將reducer'session'命名了,但'mapStateToProps'代碼是'sessionReducer'的代碼。你必須重命名其中的一個。無論何時遇到'mapStateToProps'的輸出問題,'console.log(inspect(state))'是解決問題的好方法。 – stone

+0

好吧我把一個console.log(狀態)在mapStateToProps,我有這樣的結果:'{sessionReducer:true}'這是正常的嗎? (我在代碼中爲sessionReducer重命名會話,並在api調用中將response.data返回所有用戶數據),並且我有:'userData:undefined'當我console.log控制檯組件中的道具 –