我有一个具有这种结构的应用程序
用户是否登录并不重要,TabBar 始终应该是相同的。如果用户登录应用程序将打开选项卡的内容,否则验证屏幕。如何在反应导航中创建它?抱歉,在反应导航中有些困惑。
所以我想我有一个解决方案。
App.js
screenProps
给 TabNavigator。screenProps
允许在每个选项卡中的登录状态之间切换。AsyncStorage
以便在应用程序关闭之间保持不变。注意 AsyncStorage 只允许你存储字符串。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;
订阅事件并处理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。
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