React Native-登录后如何存储身份验证令牌并导航到其他屏幕?

时间:2018-10-22 07:30:55

标签: react-native react-redux

我是React Native的新手,我正在使用Redux创建一个React Native应用程序。我只在登录页面上。目前,我成功实现了redux并在登录凭据正确时从API响应,在凭据错误时得到错误。

基本上,我遇到两个问题。

  1. 登录成功后如何导航到新屏幕?
  2. 在哪里将身份验证令牌存储在全局位置,以便我可以识别用户是否在任何页面上登录?

下面是成功登录后得到的响应

enter image description here

以下是我文件的代码。 屏幕/Login.js

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { FileSelectDirective } from 'ng2-file-upload';

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

import { ProductListComponent } from './product-list/product-list.component';

import { ProductDetailComponent } from './product-detail/product-detail.component';

import { RegisterLoginComponent } from './register-login/register-login.component';

const routes: Routes = [
  {
    path: 'products',
    component: ProductListComponent
  },
  {
    path: 'product/id',
    component: ProductDetailComponent
  },
  {
    path: 'reglogin',
    component: RegisterLoginComponent
  }
];

@NgModule({
  declarations: [
    AppComponent,
 FileSelectDirective,
 ProductListComponent,
 ProductDetailComponent,
 RegisterLoginComponent
  ],

  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule,

RouterModule,
RouterModule.forRoot(routes)
  ],

  providers: [],
  bootstrap: [AppComponent]
})


export class AppModule { }

actions / user.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { LoginComponent } from '../components/LoginComponent';
// import { Button } from 'react-native-material-design';
import { View, Text, TextInput, StatusBar, KeyboardAvoidingView } from 'react-native';
import { Button } from 'react-native-elements';
import PropTypes from 'prop-types';
import { connectAlert } from '../components/Alert';
import { login, handleEmailChange, handlePasswordChange } from '../actions/user';


class Login extends Component {

  static propTypes = {
    navigation: PropTypes.object,
    // dispatch: PropTypes.func,
    user: PropTypes.object,
    email: PropTypes.string,
    password: PropTypes.string,
    alertWithType: PropTypes.func,
    loginError: PropTypes.string
  }
  componentWillReceiveProps(nextProps) {
    // if (nextProps.loginError && nextProps.loginError !== this.props.loginError) {
    if (nextProps.loginError ) {
        this.props.alertWithType("error", "Error occurred in login", nextProps.loginError)
    }
  }
  handleSubmit = () => {
    this.props.login(this.props.email, this.props.password)
  }

  handleChange = (type, e) => {
    if (type === "email"){
      this.props.dispatch(handleEmailChange(e))
    }
    else{
      this.props.dispatch(handlePasswordChange(e))
    }
  }

  render(){
    return(
      <View style={{ flex: 1, justifyContent: 'center' }}>
      <StatusBar barStyle="default" translucent={false} />
      <KeyboardAvoidingView behavior='padding'>
        <Text style={{textAlign: 'center', fontWeight: '800'}}> AfterClix Login </Text>
        <TextInput  
               autoCapitalize="none" 
               onSubmitEditing={() => this.passwordInput.focus()} 
               autoCorrect={false} 
               keyboardType='email-address' 
               returnKeyType="next" 
               placeholder='Email' 
              //  onChangeText={event => this.handleChange("email",event)}
              onChangeText={this.props.changeEmailValue}
               placeholderTextColor='rgb(65, 146, 244)'/>
      <TextInput    
              returnKeyType="go" 
              ref={(input)=> this.passwordInput = input} 
              placeholder='Password' 
              placeholderTextColor='rgb(65, 146, 244)' 
              onChangeText={this.props.changePasswordValue}
              // onChangeText={event => this.handleChange("password",event)}
              secureTextEntry/>
        <Button raised title="Login" backgroundColor="rgb(65, 146, 244)" color="#FFFFFF" onPress={this.handleSubmit}/>
      </KeyboardAvoidingView>
    </View>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    // user: state.authentication.user
    email: state.user.email,
    password: state.user.password,
    loginError: state.user.error
  }
}

const mapDispatchToProps = dispatch => {
  return {
      changeEmailValue: (text) => dispatch({type: 'CHANGE_EMAIL_VALUE', text}),
      changePasswordValue: (text) => dispatch({type: 'CHANGE_PASSWORD_VALUE', text}),
      login: (email,password) => dispatch({type: 'LOGIN', email, password}),
  };
};


export default connect(mapStateToProps, mapDispatchToProps)(connectAlert(Login));

reducers / user.js

export const LOGIN = "LOGIN";
export const AUTHENTICATION_RESULT = "AUTHENTICATION_RESULT";
export const AUTHENTICATION_ERROR = "AUTHENTICATION_ERROR";
export const CHANGE_EMAIL_VALUE = "CHANGE_EMAIL_VALUE";
export const CHANGE_PASSWORD_VALUE = "CHANGE_PASSWORD_VALUE";

export const login = (email, password) => ({
  type: LOGIN,
  email: email,
  password: password
})

export const handleEmailChange = (value) => ({
  type: CHANGE_EMAIL_VALUE,
  email: value
})

export const handlePasswordChange = (value) => ({
  type: CHANGE_PASSWORD_VALUE,
  password: value
})

config / saga.js

import {LOGIN, AUTHENTICATION_RESULT, AUTHENTICATION_ERROR, CHANGE_EMAIL_VALUE, CHANGE_PASSWORD_VALUE} from '../actions/user'
const initialState = {
  // user: {
  //   email: '',
  //   password: '',
  //   error: null,
  // }
    email: '',
    password: '',
    error: null,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case LOGIN: 
      return {
        ...state,
        email: state.email,
        password: state.password
      }
    case CHANGE_EMAIL_VALUE:    
      // return {...state, email: action.email };
      return {...state, email: action.text };
    case CHANGE_PASSWORD_VALUE:
      return {...state, password: action.text };
    case AUTHENTICATION_RESULT:
      console.log("Result", action.result.data)
      return {...state, email: action.result.data.user.email, password: action.result.data.user.password };
        // return {
        //   ...state,
        //   user: {
        //       ...state,
        //       [action.result.base]: {
        //           ...action.result,
        //       }
        //   }
      // }
    case AUTHENTICATION_ERROR:
      return {
          ...state,
          error: action.error,
      }
    default:
      return state;
  }
}

export default reducer;

2 个答案:

答案 0 :(得分:1)

首先,您需要导入一个提供导航支持的库。

是1。登录成功后如何导航到新屏幕?

答案。选择并整合以下给出的一个库:

  1. React Navigation
  2. React Native Navigation
  3. React Native Router Flux

问题2。全局存储身份验证令牌的位置,以便我可以识别用户是否在任何页面上登录?

答案。您可以在应用重新启动时使用AsyncStorage来存储和访问用户信息,并决定是导航到主页还是登录屏幕。如果未清除存储(应用未完全关闭),则使用可以使用存储访问经过身份验证的用户

yield setItem('user', JSON.stringify(result.user)); // save user in asyncStorage - permanent
yield put({ type: AUTHENTICATION_RESULT, result }); // save user in store - temporary
yield put(NavigationActions.navigate({ routeName: 'drawerStack' })); //and then navigate to home

const setItem = async (name, data) => {
        try {
            await AsyncStorage.setItem(name, JSON.stringify(data));
            console.log('data stored');
        } catch (error) {
            // Error saving data
            console.log('AsyncStorage save error: ' + error.message);
        }
};

您可以将结果存储在storeAsyncStorage中,并在应用程序中的任何位置进行访问。

答案 1 :(得分:0)

使用现有逻辑,您可以在componentWillReceiveProps()上添加条件。 -

componentWillReceiveProps(nextProps) {
// if (nextProps.loginError && nextProps.loginError !== this.props.loginError) {
if (nextProps.loginError ) {
    this.props.alertWithType("error", "Error occurred in login", nextProps.loginError)
}
else if(nextProps.email!=='') {
 //this means you have logged in. Your navigation logic will be present here.
}

对于导航,您需要对导航库进行整数化处理,以使this.props.navigation.navigate(...)正常工作

编辑

如果您希望包含另一个定义用户登录状态的变量,则可以在

之类的componentwillreceiveprops方法中使用它
componentWillReceiveProps(nextProps) {
// if (nextProps.loginError && nextProps.loginError !== this.props.loginError) {
if (nextProps.loginError ) {
    this.props.alertWithType("error", "Error occurred in login", nextProps.loginError)
}
else if(nextProps.isAuthenticated) {
 //this means you have logged in. Your navigation logic will be present here.
}

注意-您必须更新isAuthenticated的登录成功和登录失败的还原动作,以使其正常运行。