I'm building a react native application with Expo and Firebase. I have two type of users, gymnasts and coaches. I want to show different screens for each user.
The users are stored in a Firestore collection and i'm fetching their data and performing a query to conditionally render the screens. However the code is not working and weither I log in with the role gymnast or coach, it only shows the screens for the Gymnast (which I've build first)
Can someone show me where i've made a mistake and how to navigate/conditionally render correctly?
export default function App() {
const Stack = createStackNavigator();
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [gymnastLoggedIn, setGymnastLoggedIn] = useState(false);
const [coachLoggedIn, setCoachLoggedIn] = useState(false);
const Tab = createBottomTabNavigator();
const [user, setUser] = useState("");
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
}, []);
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
firebase.firestore().collection("users").where("role", "==", "Gymnast");
setGymnastLoggedIn(true);
setCoachLoggedIn(false);
} else if (user) {
firebase.firestore().collection("users").where("role", "==", "Coach");
setCoachLoggedIn(true);
setGymnastLoggedIn(false);
} else {
setGymnastLoggedIn(false);
setCoachLoggedIn(false);
}
});
}, [user]);
if (gymnastLoggedIn == true) {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === "Home") {
iconName = focused ? "ios-home" : "ios-home-outline";
} else if (route.name === "Goals") {
iconName = focused
? "checkmark-circle"
: "checkmark-circle-outline";
} else if (route.name === "Skills") {
iconName = focused ? "flame" : "flame";
} else if (route.name === "Competition") {
iconName = focused ? "folder" : "folder-open";
} else if (route.name === "Profile") {
iconName = focused ? "person" : "person";
}
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: "#314466",
tabBarInactiveTintColor: "#665c5a",
})}
>
<Tab.Screen
name="Home"
component={HomeGymnast}
options={{ headerShown: true }}
/>
<Tab.Screen
name="Goals"
component={GoalsGymnast}
options={{ headerShown: false }}
/>
<Tab.Screen
name="Skills"
component={SkillsGymnast}
options={{ headerShown: false }}
/>
<Tab.Screen
name="Competition"
component={CompetitionGymnast}
options={{ headerShown: false }}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{ headerShown: true }}
/>
</Tab.Navigator>
</NavigationContainer>
);
} else if (coachLoggedIn == true) {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === "HomeCoach") {
iconName = focused ? "ios-home" : "ios-home-outline";
} else if (route.name === "GymnastsCoach") {
iconName = focused ? "at" : "at";
} else if (route.name === "GroupsCoach") {
iconName = focused ? "contacts" : "contacts";
} else if (route.name === "ProfileCoach") {
iconName = focused ? "person" : "person";
}
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: "#314466",
tabBarInactiveTintColor: "#665c5a",
})}
>
<Tab.Screen
name="HomeCoach"
component={HomeCoach}
options={{ headerShown: true }}
/>
<Tab.Screen
name="GymnastsCoach"
component={GymnastsCoach}
options={{ headerShown: false }}
/>
<Tab.Screen
name="GroupsCoach"
component={GroupsCoach}
options={{ headerShown: false }}
/>
<Tab.Screen
name="ProfileCoach"
component={ProfileCoach}
options={{ headerShown: true }}
/>
</Tab.Navigator>
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Login"
component={Login}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ headerShown: false }}
/>
<Stack.Screen
name="PageOne"
component={PageOne}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
}
CodePudding user response:
The following query will return all the users who have role Gymnast and same goes for the Coach role.
firebase.firestore().collection("users").where("role", "==", "Gymnast");
Instead you should create a document for each user in the users collection and store their role as shown below:
users -> {userId} // user ID from Firebase Authentication
{
role: "gymnast",
...otherUserData
}
Then you can read their document after user logs in as shown below:
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userRole, setUserRole] = useState("");
// only one useEffect here
useEffect(() => {
firebase.auth().onAuthStateChanged(async (user) => {
if (user) {
setIsLoggedIn(true);
const userDocSnap = await firebase.firestore().collection("users").doc(user.uid).get();
if (userDocSnap.exists) {
const userData = userDocSnap.data();
} else {
console.log("user document missing")
}
} else {
setIsLoggedIn(false);
}
});
}, []);
Then instead of if (gymnastLoggedIn == true)
in your components, use if (role === "gymnast")
and render Gymnast component if true.