根据登录令牌在屏幕之间进行本机切换

时间:2018-06-04 16:11:53

标签: javascript android reactjs react-native

我正在构建一个反应原生应用程序,我是新手。我目前有3个文件 -

1)App.js

2)Login.js

3)FlightList.js

当我还没有登录时,我需要显示登录屏幕。当我登录时,我需要存储令牌并显示航班列表屏幕。

这是我的代码 -

App.js

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import Login from './Login';

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        //Check if token is there and if there show flight list screen else login screen
      </View>
    );
  }
}

Login.js

'use strict';
import React, { Component } from 'react';
import {
  StyleSheet,
  TextInput,
  TouchableHighlight,
  AsyncStorage,
  Text,
  View
} from 'react-native';
import {
    StackNavigator,
  } from 'react-navigation';
  import FlightList from './FlightList';


  const FlightListScreen = StackNavigator({
    FlightList: { screen: FlightList }
  });

const ACCESS_TOKEN = 'access_token';

export default class Login extends Component {
  constructor(props){
    super(props);

    this.state = {
      email: "",
      password: "",
      error: ""
    }
  }


async storeToken(accessToken){
      try {
          await AsyncStorage.setItem(ACCESS_TOKEN, accessToken);
      } catch (error) {
          console.log("something went wrong");
      }
    }

  async onLoginPressed() {
    try {
      const reqOptions = {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({

            email: this.state.email,
            password: this.state.password,

        })
      };

      console.log("error of json is " + JSON.stringify(reqOptions))
      let response = await fetch('https://...login', reqOptions);

      if (response.status >= 200 && response.status < 300) {
        const body = await response.json();
          this.storeToken(body.token);
          this.props.navigation.navigate('FlightListScreen');
      } else {
          //Handle error
          let error = res;
          throw error;
      }
    } catch(error) {
        this.setState({error: error});
        console.log("error " + error);
    }
  }
  render() {

    return (
      <View style={styles.container}>
      //view here
      </View>
    );
  }
}

FlightList.js

'use strict';
import React, { Component } from 'react';
import {
  StyleSheet,
  TextInput,
  TouchableHighlight,
  AsyncStorage,
  Text,
  View
} from 'react-native';
import {
    StackNavigator,
  } from 'react-navigation';

const ACCESS_TOKEN = 'access_token';

export default class FlightList extends Component {
  constructor(props){
    super(props);
  }


async getToken() {
    try {
        let token = await AsyncStorage.getItem(ACCESS_TOKEN);
        console.log("token is" + token);
    } catch (error) {
        console.log("error while getting token");
    }
 }

 async getFlights() {
    try {
        const reqOptions = {
          method: 'GET',
          headers: {
            Authorization: `Bearer ${getToken()}`
          },
          body: JSON.stringify({
            // no body since it is GET call

          })
        };

        let response = await fetch('https://.../flights', reqOptions);

        if (response.status >= 200 && response.status < 300) {
          const body = await response.json();
          //update the view
        } else {
            //Handle error
            let error = res;
            throw error;
        }
      } catch(error) {
          this.setState({error: error});
          console.log("error " + error);
      }
 }



 componentDidMount(){
    getFlights();
  }
}

我的问题是 -

1)在App.js中,如何检查令牌是否存在以及是否显示航班列表屏幕,否则登录界面

2)另外getToken()方法如何全局使用它,因为我需要它作为所有API调用的标题

2 个答案:

答案 0 :(得分:1)

You can create two other files, the first one is a utility file contains all your necessary functions you need to define global. For example your getToken will be like this:

export default class Utility {

    static async getToken() {
        try {
            let token = await AsyncStorage.getItem(ACCESS_TOKEN);
            return token
        } catch (error) {
            console.log("error while getting token");
            return 'error
        }
    }
}

If you use static before your function, you can use that function every where you import Utility file.

and for your first question... you can make an splash screen and check the token and decide to navigate to which page. I advise you to create a file for your api requests and another file for router. you can define all routing definition in router.js and start app with it:

import React, { Component } from 'react';
import { View } from 'react-native';
import { StackNavigator, TabRouter, DrawerNavigator } from 'react-navigation';
import Splash from './../views/SplashScreen'
import Login from './../views/Login'
import Verification from './../views/Verification'
import Home from './../views/Home'
import Contents from './../views/Contents'
import ContentList from './../views/ContentList'
import MessageInbox from './../views/MessageInbox'

export default class AppRouter extends Component {

    public static Routes = StackNavigator({
    SplashScreen: { screen: Splash },
    Login: { screen: Login },
    Verification: { screen: Verification },
    Private: {
        screen: DrawerNavigator({
            Main: {
                screen: StackNavigator({
                    Home: { screen: Home },
                    Contents: { screen: Contents },
                    ContentList: { screen: ContentList },
                }, { initialRouteName: 'Home' })
            },
            MessageInbox: { screen: MessageInbox },
        }, { initialRouteName: 'Main' })
    }
}, { initialRouteName: 'SplashScreen' })

render() {
    return (
        <View></View>
    )
}

}

and index.js will be:

import React, { Component } from 'react';
import AppRouter from './../router/routes';
export default class App extends Component {
    render() {
        return (
            <AppRouter.Routes />
        )
    }
}

I hope i can help you

EDIT:

If you use AppRouter, it will be the starter of your app and the first page called by it so it has a navigation prop. If you want to navigate to each page, you can just use this.props.navigation.navigate('FlightList') . remember that if you are using a component in a page and you want to navigate from this component, you need to pass this.props.navigation as a prop to that component and then, it can change the stack navigation. in your case, your pages will be something like this...:

Router.js

export default class AppRouter extends Component {

public static Routes = StackNavigator({
    SplashScreen: { screen: Splash },
    Login: { screen: Login },
    FlightList: { screen: FlightList},
}, { initialRouteName: 'SplashScreen' })

render() {
    return (
        <View></View>
    )
}
}

SplashScreen.js:

export default class SplashScreen extends Component {
constructor(props) {
    super(props);
    let token = Check token...
    if (token) {
        this.props.navigation.navigate('FlightList')
    } else {
        this.props.navigation.navigate('Login')
    }
}
render() {
    return (
        <View style={{ flex: 1 }}>
            <Text>Loading...</Text>
        </View>
    )
}
}

答案 1 :(得分:0)

So I have a very similar problem. I solved it by creating a loading screen and on componentDidMount I called a function that like your getToken request fetches the token it also makes a decision once I have a value back from storage to go to the login page or my other page based on if I get a value back or not.