我有一个具有这种结构的应用程序
用户是否登录都没有关系,TabBar始终应该相同。如果用户登录了应用程序将打开选项卡的内容,否则将打开“身份验证”屏幕。如何在反应导航中创建它? 抱歉,在反应导航中有些困惑。
答案 0 :(得分:1)
所以我想我有一个解决方案。
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 />;
}
}
}
在render函数中,根据所传递的值,我们将访问从screenProps
传递来的TabNavigator
,具体取决于呈现的内容。
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>
);
}
}
这是一个示例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