0

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

结构体

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

4

1 回答 1

1

所以我想我有一个解决方案。

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

事件发射器

要创建事件发射器,我们需要使用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;

应用程序.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;
    }
  }
}

选项卡屏幕模板

这是每个 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 />;
    }
  }
}

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

一个样品AuthScreen

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

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>
    );
  }
}

示例 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);

小吃

最后,这里有一份小吃,显示一切正常https://snack.expo.io/@andypandy/event-emitter-to-handle-login

于 2019-02-27T18:31:50.037 回答