在每个选项卡中使用Auth屏幕进行反应导航

问题描述 投票:0回答:1

我有一个这种结构的应用程序

structure

用户是否登录并不重要,TabBar应始终相同。如果用户登录应用程序将打开选项卡的内容,否则将打开Auth屏幕。如何在反应导航中创建它?对不起,反应导航有点困惑。

reactjs navigation react-navigation react-navigation-stack
1个回答
1
投票

所以我认为我有一个解决方案。

  1. 创建一个事件发射器,它将在登录状态更改时发出事件
  2. 订阅App.js的活动
  3. 将更新的事件通过screenProps传递给TabNavigator。
  4. 这些更新的screenProps允许在每个选项卡中的登录状态之间切换。
  5. 将登录状态存储在AsyncStorage中,以便在应用程序关闭之间保持持久状态。请注意,AsyncStorage仅允许您存储字符串。
  6. 用户登录时从AuthScreen发送事件,或者在用户注销时从其他屏幕发送事件。

Event Emitter

要创建事件发射器,我们需要使用events依赖项。用npm i events安装它。我们将它创建为单例,以便我们只能在我们的应用程序中运行一个这样的实例。

import { EventEmitter } from 'events';

class LoginEventEmitter {
  constructor () {
    this.eventEmitter = new EventEmitter();
  }

  // create a function to handle the login
  // pass the loggedIn value that you want to be emitted
  handleLogin = (loggedIn) => {
    this.eventEmitter.emit('loggedIn', { loggedIn });
  }
}

const EventEmitterController = new LoginEventEmitter();

export default EventEmitterController;

App.js

订阅活动并处理AsyncStorage

import React from 'react';
import { AsyncStorage } from 'react-native';
import AppContainer from './MainNavigation';
import LoginEventEmitter from './LoginEventEmitter';
export default class App extends React.Component {
  constructor (props) {
    super(props);

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

    // subscribe to the events and update the values in state and in AsyncStorage
    LoginEventEmitter.eventEmitter.addListener('loggedIn', e => {
      this.setState({ loggedIn: e.loggedIn });
      let value = e.loggedIn ? 'true' : 'false';
      AsyncStorage.setItem('loggedIn', value);
    });
  }

  async componentDidMount () {
    // handle the loggedIn value when the component mounts
    try {
      let loggedIn = await AsyncStorage.getItem('loggedIn');
      if (loggedIn) {
        this.setState({
          loggedIn: loggedIn === 'true',
          loaded: true
        });
      } else {
        this.setState({ loaded: true });
      }
    } catch (error) {
      console.warn(error);
    }
  }

  render () {
    // wait until asyncstorage has returned a value before showing the App.
    // pass the loggedIn value via screen props so every screen in the TabNavigator gets updated with the new value
    if (this.state.loaded) {
      return (
        <AppContainer screenProps={{ loggedIn: this.state.loggedIn }}/>
      );
    } else {
      return null;
    }
  }
}

Template for Tab Screen

这是每个TabScreen的基本模板。我在其上放了一个注销按钮,以便用户可以注销。 (这主要用于测试)。

import React from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import AuthScreen from './AuthScreen';
import LoginEventEmitter from './LoginEventEmitter';

export default class Screen1 extends React.Component {
  logout = () => {
    LoginEventEmitter.handleLogin(false);
  }

  render () {
    if (this.props.screenProps.loggedIn) {
      return (
        <View style={styles.container}>
          <Text>Screen 1</Text>
          <Button title={'logout'} onPress={this.logout} />
        </View>
      );
    } else {
      return <AuthScreen />;
    }
  }
}

请注意,在render函数中,我们访问从screenProps传递的TabNavigator,具体取决于传递的值取决于渲染的内容。

A sample AuthScreen

在这里,当用户点击按钮时,我们执行“登录”。这会发出一个由App.js中的侦听器捕获的事件,该事件反过来更新App.js中的状态值,并且该值通过screenProps传递给每个Tab。

import React from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import LoginEventEmitter from './LoginEventEmitter';
export default class Screen1 extends React.Component {
  render () {
    return (
      <View style={styles.container}>
        <Text>AuthScreen</Text>
        <Button title={'Login'} onPress={() => {
          LoginEventEmitter.handleLogin(true);
        }}/>
      </View>
    );
  }
}

Sample TabNavigator

以下是TabNavigator示例。

import Screen1 from './Screen1';
import Screen2 from './Screen2';
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';

const screens = {
  Screen1: {
    screen: Screen1
  },
  Screen2: {
    screen: Screen2
  }
};

const config = {
  headerMode: 'none',
  initialRouteName: 'Screen1'
};

const MainNavigator = createBottomTabNavigator(screens, config);
export default createAppContainer(MainNavigator);

Snack

最后这里是一个小吃,显示它所有工作https://snack.expo.io/@andypandy/event-emitter-to-handle-login

© www.soinside.com 2019 - 2024. All rights reserved.