Так что я думаю, что у меня есть решение.
- Создание источника событий, который будет генерировать события при изменении состояния входа в систему
- Подписаться на события в
App.js
- Передайте обновленные события через
screenProps
в TabNavigator. - Эти обновленные
screenProps
позволяют переключаться между зарегистрированными состояниями на каждой вкладке. - Сохранять зарегистрированное состояние в
AsyncStorage
, чтобы оно сохранялось между закрытиями приложений.Обратите внимание, что AsyncStorage позволяет только хранить строки. - Отправка событий из
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