2017-10-08 187 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控制台组件中的道具 –