Реагируйте с навигацией на экране авторизации в каждой вкладке - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть приложение с такой структурой

structure

Не имеет значения, вошел ли пользователь в систему или нет, TabBar всегда долженбыть таким же.Если пользователь вошел в приложение, откроется содержимое вкладки, в противном случае экран авторизации.Как я могу создать это в реагировать-навигации?Извините, немного запутался в реакции-навигации.

1 Ответ

0 голосов
/ 27 февраля 2019

Так что я думаю, что у меня есть решение.

  1. Создание источника событий, который будет генерировать события при изменении состояния входа в систему
  2. Подписаться на события в App.js
  3. Передайте обновленные события через screenProps в TabNavigator.
  4. Эти обновленные screenProps позволяют переключаться между зарегистрированными состояниями на каждой вкладке.
  5. Сохранять зарегистрированное состояние в AsyncStorage, чтобы оно сохранялось между закрытиями приложений.Обратите внимание, что AsyncStorage позволяет только хранить строки.
  6. Отправка событий из AuthScreen, когда пользователь входит в систему, или из других экранов, когда пользователь выходит из системы.

Emitter Event

Чтобы создатьгенератор событий, нам нужно использовать зависимость 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;
    }
  }
}

Шаблон для экрана вкладок

Это основнойшаблон для каждого 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

...