[英]How do I render different Screens of an iOS app with React Native and Firebase/Firestore based on a user's role (provider or customer) after login?
I'm creating an app with React Native and Firebase/Firestore, and I need the app to show different screens based on the role of the user's account (Provider or Customer).我正在使用 React Native 和 Firebase/Firestore 创建一个应用程序,我需要该应用程序根据用户帐户(提供商或客户)的角色显示不同的屏幕。 After a user logs into their account, the app should check their role data from Firebase and render a different screen based on it.
用户登录他们的帐户后,应用程序应该从 Firebase 检查他们的角色数据并根据它呈现不同的屏幕。 So the app will first evaluate the condition to see if they're logged in. Then it will evaluate the condition to see if they're a Provider or Customer and then render the proper screen (either the Login, ProviderHomeScreen, or CustomerHomeScreen).
因此,应用程序将首先评估条件以查看他们是否已登录。然后它将评估条件以查看他们是提供者还是客户,然后呈现正确的屏幕(登录、ProviderHomeScreen 或 CustomerHomeScreen)。
I've tried to use the condition:我尝试使用以下条件:
const user = firebase.auth().currentUser;
var role;
if (user != null) {
role = user.role;
console.log(role);
}
if (isLoggedIn) {
if (user.role === 'provider') {
return (
<NavigationContainer>
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Provider Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<CustomerStack.Navigator>
<Stack.Screen
name={'Customer Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name={'Search'}
component={SearchScreen}
options={{
title: 'Search Availa Providers',
}}
/>
</CustomerStack.Navigator>
</NavigationContainer>
);
}
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen
name="Customer Sign-up"
component={CustomerRegistrationScreen}
/>
<Stack.Screen
name="Provider Sign-up"
component={ProviderRegistrationScreen}
/>
</Stack.Navigator>
</NavigationContainer>
but when I console.log the user.role, it says undefined in the console, and the app just renders the CustomerHomeScreen with the CustomerHomeTabNavigator.但是当我对 user.role 进行控制台登录时,它在控制台中显示未定义,并且该应用程序仅使用 CustomerHomeTabNavigator 呈现 CustomerHomeScreen。 Please help me successfully access the role data of the currently signed-in user from Firestore and create conditions to render the proper screens for the proper role of the users.
请帮助我从 Firestore 成功访问当前登录用户的角色数据,并创造条件为用户的正确角色呈现正确的屏幕。
Right now, this is what my code looks like for App.js:现在,这就是我的 App.js 代码的样子:
import 'react-native-gesture-handler';
import React, {useEffect, useState} from 'react';
import {View, Text} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {createStackNavigator} from '@react-navigation/stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import CustomerHomeScreen from '../Availa/src/Customer/screens/Home/index';
import Fontisto from 'react-native-vector-icons/Fontisto';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Feather from 'react-native-vector-icons/Feather';
import AntDesign from 'react-native-vector-icons/AntDesign';
import Ionicons from 'react-native-vector-icons/Ionicons';
import {firebase} from '../Availa/src/firebase/config';
import 'firebase/auth';
import firestore from '@react-native-firebase/firestore';
import 'firebase/firestore';
import 'react-native-gesture-handler';
Fontisto.loadFont();
FontAwesome.loadFont();
Feather.loadFont();
AntDesign.loadFont();
Ionicons.loadFont();
import SearchScreen from '../Availa/src/Customer/screens/SearchScreen/index';
import ProfileScreen from '../Availa/src/Customer/screens/ProfileScreen/index';
import {
LoginScreen,
CustomerRegistrationScreen,
ProviderRegistrationScreen,
} from './src/screens';
import 'firebase/auth';
import {decode, encode} from 'base-64';
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob) {
global.atob = decode;
}
const ProviderStack = createNativeStackNavigator();
const ProviderStackScreen = () => {
return (
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
);
};
const ProviderTab = createBottomTabNavigator();
const ProviderHomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#007FFF',
}}>
<Tab.Screen
name={'Provider'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Fontisto name="home" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'My List'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<FontAwesome name="heart-o" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Appointments'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="calendar" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Messages'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Feather name="message-square" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="person-circle-outline" size={25} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
const CustomerStack = createNativeStackNavigator();
const CustomerStackScreen = () => {
return (
<CustomerStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</CustomerStack.Navigator>
);
};
const Tab = createBottomTabNavigator();
const CustomerHomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#1cd478',
}}>
<Tab.Screen
name={'Home'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Fontisto name="home" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'My List'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<FontAwesome name="heart-o" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Appointments'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="calendar" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Messages'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Feather name="message-square" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="person-circle-outline" size={25} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
const chooseScreen = user => {
if (user?.role === 'provider') {
ProviderStackScreen();
}
CustomerStackScreen();
};
const Stack = createStackNavigator();
export default function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
const firestore = firebase.firestore;
const auth = firebase.auth;
const user = firebase.auth().currentUser;
// //to check if Firebase has been initialized
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
} else {
firebase.app();
}
firebase.auth().onAuthStateChanged(user => {
if (user != null) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
var role;
if (user != null) {
role = user.role;
console.log(role);
}
if (isLoggedIn) {
if (user.role === 'provider') {
return (
<NavigationContainer>
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Provider Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<CustomerStack.Navigator>
<Stack.Screen
name={'Customer Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name={'Search'}
component={SearchScreen}
options={{
title: 'Search Availa Providers',
}}
/>
</CustomerStack.Navigator>
</NavigationContainer>
);
}
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen
name="Customer Sign-up"
component={CustomerRegistrationScreen}
/>
<Stack.Screen
name="Provider Sign-up"
component={ProviderRegistrationScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
Also, this is what my LoginScreen.js looks like:此外,这就是我的 LoginScreen.js 的样子:
import React, {useState} from 'react';
import {Image, Text, TextInput, TouchableOpacity, View} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import styles from './styles';
import {firebase} from '../../firebase/config';
export default function LoginScreen({navigation}) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const onLoginPress = () => {
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(response => {
const uid = response.user.uid;
const usersRef = firebase.firestore().collection('users');
usersRef
.doc(uid)
.get()
.then(firestoreDocument => {
if (!firestoreDocument.exists) {
alert('User does not exist');
return;
}
const user = firestoreDocument.data();
if (user.role === 'provider') {
navigation.navigate('Provider Home', {user});
} else {
navigation.navigate('Customer Home', {user});
}
})
.catch(error => {
alert(error);
});
})
.catch(error => {
alert(error);
});
};
return (
<View style={styles.container}>
<KeyboardAwareScrollView
style={{flex: 1, width: '100%'}}
keyboardShouldPersistTaps="always">
<Image
style={styles.logo}
source={require('../../../assets/availalogo.png')}
/>
<TextInput
style={styles.input}
placeholder="Email"
placeholderTextColor="#aaaaaa"
onChangeText={text => setEmail(text)}
value={email}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholderTextColor="#aaaaaa"
secureTextEntry
placeholder="Password"
onChangeText={text => setPassword(text)}
value={password}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TouchableOpacity style={styles.button} onPress={() => onLoginPress()}>
<Text style={styles.buttonTitle}>Log in</Text>
</TouchableOpacity>
<Text style={styles.footerText}>Don't have an account?</Text>
<TouchableOpacity
style={{
backgroundColor: '#ED2939', //#118C4F?
marginLeft: 30,
marginRight: 30,
marginTop: 20,
height: 48,
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => navigation.navigate('Provider Sign-up')}>
<Text style={{color: 'white', fontSize: 16, fontWeight: 'bold'}}>
Sign Up as Availa Provider
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: '#007FFF',
marginLeft: 30,
marginRight: 30,
marginTop: 20,
height: 48,
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => navigation.navigate('Customer Sign-up')}>
<Text style={{color: 'white', fontSize: 16, fontWeight: 'bold'}}>
Sign Up as Customer
</Text>
</TouchableOpacity>
</KeyboardAwareScrollView>
</View>
);
}
Are you adding the role in custom claims?您是否在自定义声明中添加角色?
if so you need to get the the claims from getIdTokenResult如果是这样,您需要从 getIdTokenResult 获取声明
firebase.auth().currentUser.getIdTokenResult()
.then((idTokenResult) => {
const role = idTokenResult.claims.role;
})
.catch((error) => {
console.log(error);
});
Also I personally keep the firebase initialization outside of the component and此外,我个人将 firebase 初始化保留在组件之外,并且
firebase.auth().onAuthStateChanged(user => {
if (user != null) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
inside useEffect
, so instead of setIsLoggedIn
would do setUser
and in your case after you get the role you can set it in a different state.在
useEffect
内部,因此setIsLoggedIn
将代替setUser
,在您获得角色后,您可以将其设置为不同的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.