React Native - Как сохранить токен авторизации и перейти на другой экран после входа в систему? - PullRequest
0 голосов
/ 22 октября 2018

Я новичок в реагировании на нативном, я создаю одно реагировать нативное приложение с редуксом.Я только на странице входа.В настоящее время я успешно внедрил Redux и получаю ответ от API, если учетные данные для входа в систему верны, и получаю ошибку, если учетные данные неверны.

В основном у меня есть 2 вопроса, в которых я застрял.

  1. Как перейти на новый экран при успешном входе в систему?
  2. Где хранить токен авторизации глобально, чтобы я мог идентифицировать пользователя, вошедшего в систему или нет на какой-либо странице?

Ниже приведеныОтвет, который я получаю при успешном входе в систему

enter image description here

Ниже приведен код для моих файлов.экранов / Login.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));

actions / 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
})

redurs / 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;

config / saga.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);
}

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Используя существующую логику, вы можете добавить условие на 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 иошибка входа редуцирует действия для правильного поведения.

0 голосов
/ 22 октября 2018

Прежде всего вам необходимо импортировать библиотеку, которая обеспечивает поддержку навигации.

Ques 1. Как перейти на новый экран, если вход выполнен успешно?

Ответ. Выберите и интегрируйте один из следующих библиотек:

  1. Реагируйте с навигацией
  2. Реагируйте с собственной навигацией
  3. React Native Router Flux

Ques 2. Где хранить токен авторизации глобально, чтобы я мог идентифицировать пользователя, вошел в систему или нетлюбая страница?

Ответ. Вы можете использовать AsyncStorage для хранения и доступа к пользовательской информации при перезапуске приложения и принятии решения о переходе на домашний экран или экран входа в систему.,Если хранилище не очищено (приложение закрыто не полностью), то можно использовать 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);
        }
};

, вы можете сохранить результат в store, а также AsyncStorage и получить к нему доступ.в любом месте приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...