如何使用AsyncStorage在React Native中隐藏登录屏幕

时间:2018-07-27 09:36:54

标签: javascript react-native

当我已经使用AsyncStorage登录时,我想隐藏登录屏幕并切换到其他屏幕。

这是我的代码:

import React from 'react';

// Navigators
import { createBottomTabNavigator, createStackNavigator } from 'react-navigation';

import Login from './Login'
import Home from './Home'
import Control from './Control'
import Setting from './Setting'
import Info from './Info'

/* Home Stack */
const HomeStack = createStackNavigator({ Home: { screen: Home } });

/* ControlStack */
const ControlStack = createStackNavigator({ Control: { screen: Control } });

/* SettingStack */
const SettingStack = createStackNavigator({ Setting: { screen: Setting } });

/* InfoStack */
const InfoStack = createStackNavigator({ Info: { screen: Info } });

const Tabs = createBottomTabNavigator({
    HomeStack: { screen: HomeStack },
    ControlStack: { screen: ControlStack },
    SettingStack: { screen: SettingStack },
    InfoStack: { screen: InfoStack },
}, {
    navigationOptions: ({ navigation }) => ({
        tabBarIcon: ({ focused, tintColor }) => {
            const { routeName } = navigation.state;
            let iconName;
            if (routeName === 'HomeStack') {
                iconName = 'home';
            } else if (routeName === 'ControlStack') {
                iconName = 'sliders';
            } else if (routeName === 'SettingStack') {
                iconName = 'settings';
            } else if (routeName === 'InfoStack') {
                iconName = 'user';
                // iconName = `ios-options${focused ? '' : '-outline'}`;
            }

            return <Icons name={iconName} size={25} color={tintColor} />;
        },
    }),
    tabBarOptions: {
        activeTintColor: '#2fb581',
        inactiveTintColor: 'gray',
        style: {
            backgroundColor: '#f7f7f7',
            borderTopWidth: 1,
            borderTopColor: '#f7f7f7'
        },
        showLabel: false,
    },
    initialRouteName: 'HomeStack'
});

var res;
try {
    AsyncStorage.getItem('id_token').then((result) => {
        res = result;
    });
    alert(res);
} catch (error) {
    alert(error);
}

/* Login Stack */
const LoginStack = createStackNavigator({
    Login: { 
        screen: Login, 
        header: { visible: false }
    },
    Tabs: { 
        screen: Tabs,
        header: { visible: false }
    },
    Main: { 
        screen: Main,
        header: { visible: false }
    },
}, {
    initialRouteName: typeof res !== 'undefined' ? 'Tabs' : 'Login',
    headerMode: 'none'
});

export default LoginStack;

我想在已经登录或拥有令牌时显示“标签”屏幕,而在没有令牌时显示“登录”屏幕。

类似于此代码:

initialRouteName: typeof res !== 'undefined' ? 'Tabs' : 'Login',

我已经登录并具有令牌,但是我总是在AyncStorage结果中得到结果“ undefined”。

当我登录并显示“选项卡”屏幕时,如何使AsyncStorage提供令牌结果?

3 个答案:

答案 0 :(得分:0)

首先创建一个DropdownMenuItem。几乎所有的应用程序都有这个。 然后,您可以在用户为空时设置超时时间,否则可以显示一段时间。

import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final String data =
      '[{"ID": 1, "Code": "01", "Description": "REGION I (ILOCOS REGION)", "PSGCCode": "010000000"}, {"ID": 2, "Code": "02", "Description": "REGION II (CAGAYAN VALLEY)", "PSGCCode": "020000000"}]';
  List<Region> _region = [];
  String selectedRegion;

  @override
  Widget build(BuildContext context) {
    final json = JsonDecoder().convert(data);
    _region = (json).map<Region>((item) => Region.fromJson(item)).toList();
    selectedRegion = _region[0].regionDescription;

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            DropdownButtonHideUnderline(
              child: new DropdownButton<String>(
                hint: new Text("Select Region"),
                value: selectedRegion,
                isDense: true,
                onChanged: (String newValue) {
                  setState(() {
                    selectedRegion = newValue;
                  });
                  print(selectedRegion);
                },
                items: _region.map((Region map) {
                  return new DropdownMenuItem<String>(
                    value: map.regionDescription,
                    child: new Text(map.regionDescription,
                        style: new TextStyle(color: Colors.black)),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class Region {
  final int regionid;
  final String regionDescription;

  Region({this.regionid, this.regionDescription});
  factory Region.fromJson(Map<String, dynamic> json) {
    return new Region(
        regionid: json['ID'], regionDescription: json['Description']);
  }
}
  

如果该代码在缓存中找到用户,它将立即加载SplashScreen。   或者,如果用户为null,则将重定向到AsyncStorage.getItem(PrefConstants.UserDetail).then(value => { if(value){ this.changeView("ScreenDashboard"); } else { this.setTimeout(() => { _this.changeView("ScreenLogin"); }, 2000); } changeView(value){ const resetAction = StackActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: value ? "ScreenDashboard" : "ScreenLoginFb" }) ] }); this.props.navigation.dispatch(resetAction); }

请注意,SplashScreen将成为应用程序的启动屏幕。

答案 1 :(得分:0)

我强烈建议您使用React Navigation 2中的SwitchNavigator

有关更多信息,请阅读Authentication Flow

  
      
  • 用户打开应用程序。

  •   
  • 该应用会从持久性存储(例如AsyncStorage)中加载某些身份验证状态。

  •   
  • 加载状态后,将根据是否有效向用户显示身份验证屏幕或主应用程序   身份验证状态已加载。

  •   
  • 用户注销后,我们清除身份验证状态,并将其发送回身份验证屏幕。
  •   

这里是一个例子:

const SwitchNavigator = createSwitchNavigator(
  {
    AuthLoading: RouterScreen,
    App: Tabs,
    Auth: LoginScreen
  },
  {
    initialRouteName: 'AuthLoading',
  }
);

在RouterScreen中:

constructor(props) {
  super(props);
  AsyncStorage.getItem('id_token').then((userToken) => {
    this.props.navigation.navigate(userToken ? 'App' : 'Auth');
 }
}

将RouterScreen设计为您的SplashScreen,或显示诸如ActivityIndi​​cator之类的东西。

答案 2 :(得分:0)

如果您要手动操作,这就是我的操作方式,我使用的不是AsyncStorage,而是普通的sqlite数据库,即使屏幕的逻辑是一样的。 我仅在没有用户数据时显示“登录”屏幕,如果找到存储的内容,则会直接进入下一个屏幕。

main.js

import LoginScreen from './components/login';
  export default class Main extends Component {

   constructor(props) {
    super(props);

    this.state = {
      loggedIn: false,
    };
   }

  componentDidMount() {

     login=(user,pass)=>{
       //check if there is something already saved with AsyncStorage
         //if not, read the user and pass parameters
         //if there's something already saved
           console.log("Bienvenido");
           this.setState({
             loggedIn: true
           });
     }
  }


  render() {
     if(this.state.loggedIn === true){
        return (
          <View style={styles.container}>
          </View>
        );
      }
      else {
            return (
            <LoginScreen login={this.login.bind(this)}>
            </LoginScreen>
            );
   }

}

这就是我将用户名和密码从login.js发送到main.js的方式

<TouchableOpacity
  onPress={this.props.login.bind(this,this.state.username, this.state.password)}>
   <View style={styles.loginButton} >
     <Text style={styles.loginButtonText}>LOG IN</Text>
   </View>
</TouchableOpacity>

大部分代码由gedeagas制作,因为我正在使用他的react-native-musicplayer-ui