首页 > 解决方案 > React Native - 登录后如何存储身份验证令牌并导航到其他屏幕?

问题描述

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

基本上,我有两个问题被困在其中。

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

以下是我登录成功时得到的响应

在此处输入图像描述

以下是我的文件的代码。屏幕/登录.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));

动作/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
})

减速器/user.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;

配置/传奇.js

import { takeEvery, select, call, put } from 'redux-saga/effects';
import { LOGIN, AUTHENTICATION_RESULT, AUTHENTICATION_ERROR } from '../actions/user';

const authenticateUser = (email, password) => fetch('apiURL/oauth/token', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: email,
    password: password,
    grant_type: "password"
  }),
});
function* fetchUser(action){
    try{
      console.log("Email", action.email)
      console.log("Password", action.password)
      const response = yield call(authenticateUser, action.email, action.password)
      const result = yield response.json();
      if (result.error) {
          yield put({ type: AUTHENTICATION_ERROR, error: result.error });
      } else {
          yield put({ type: AUTHENTICATION_RESULT, result });
      }
    }
    catch (e) {
      yield put({ type: AUTHENTICATION_ERROR, error: e.message });
    }
}
export default function* rootSaga() {
    yield takeEvery(LOGIN, fetchUser);
}

标签: react-nativereact-redux

解决方案


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

问题 1.登录成功后如何跳转到新界面?

回答。选择并集成下面给出的库之一:

  1. 反应导航
  2. 反应原生导航
  3. 反应本机路由器通量

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

回答。您可以使用AsyncStorage在应用重新启动时存储和访问用户信息,并决定是导航到主屏幕还是登录屏幕。当 store 未清空时(app 未完全关闭),则可以使用 store 访问认证用户

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可以在任何位置访问它。


推荐阅读