Home > front end >  React Navigation Show Different Tabs On Login
React Navigation Show Different Tabs On Login

Time:05-03

I am using react-navigation with a bottom tab navigator. When the app is started, it fetches the data from persistent data storage and shows the correct tabs depending on whether the user is logged in or not. However, once the user logs in, the app had to be closed and reopened for the correct tabs to be shown.

Here is my code for App.js:

import React, { useState } from "react";

import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";

import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";

import { getGlobalState, setGlobalState } from "./src/GlobalState";

const Tab = createBottomTabNavigator();

export default function App() {
  let [fontsLoaded] = useFonts({
    Recursive_300,
  });

  const [isChecking, setIsChecking] = useState(true);

  const [isSignedIn, setIsSignedIn] = useState(null);

  async function getUserData() {
    const username = await SecureStore.getItemAsync("blogger101_Username");
    const password = await SecureStore.getItemAsync("blogger101_Password");
    const email = await SecureStore.getItemAsync("blogger101_Email");
    setGlobalState("username", username);
    setGlobalState("password", password);
    setGlobalState("email", email);
    if (username === null) {
      setIsSignedIn(false);
    } else {
      setIsSignedIn(true);
    }
  }

  if (isChecking) {
    return (
      <AppLoading
        startAsync={getUserData}
        onFinish={() => setIsChecking(false)}
        one rror={console.warn}
      />
    );
  } else {
    if (getGlobalState("username") === null && isSignedIn !== false) {
      setIsSignedIn(false);
    } else if (getGlobalState("username") !== null && isSignedIn !== true) {
      setIsSignedIn(true);
    }
  }

  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({ route }) => ({
          tabBarButton: [
            "Details",
          ].includes(route.name)
            ? () => {
                return null;
              }
            : undefined,
          tabBarIcon: ({ focused, color, size }) => {
            if (route.name === "Blogs") {
              return <Entypo name="text-document" size={size} color={color} />;
            } else if (route.name === "Post_Blog") {
              return <Entypo name="new-message" size={size} color={color} />;
            } else if (route.name === "Login") {
              return <SimpleLineIcons name="login" size={size} color={color} />;
            } else if (route.name === "Sign_Up") {
              return <Feather name="user-plus" size={size} color={color} />;
            } else if (route.name === "Logout") {
              return (
                <SimpleLineIcons name="logout" size={size} color={color} />
              );
            }
          },
          tabBarActiveTintColor: "tomato",
          tabBarInactiveTintColor: "gray",
        })}
      >
        <Tab.Screen
          name="Blogs"
          component={Blogs}
          initialParams={{ message: "" }}
          options={{
            headerLeft: (props) => (
              <Entypo name="text-document" size={26} color="black" />
            ),
            headerLeftContainerStyle: { paddingLeft: 10 },
            headerRightContainerStyle: { paddingRight: 10 },
          }}
        />
  
        {isSignedIn ? (
          <Tab.Screen
            name="Post_Blog"
            component={PostBlog}
            options={{
              headerLeft: (props) => (
                <Entypo name="new-message" size={26} color="black" />
              ),
              headerLeftContainerStyle: { paddingLeft: 10 },
              headerRightContainerStyle: { paddingRight: 10 },
            }}
          />
        ) : <Tab.Screen
            name="Sign_Up"
            component={Sign_Up}
            options={{
              headerLeft: (props) => (
                <Feather name="user-plus" size={20} color="black" />
              ),
              headerLeftContainerStyle: { paddingLeft: 10 },
              headerRightContainerStyle: { paddingRight: 10 },
            }}
          />
        }

        {isSignedIn ? (
          <Tab.Screen name="Logout" component={Logout} />
        ) : <Tab.Screen
            name="Login"
            component={Login}
            options={{
              headerLeft: (props) => (
                <SimpleLineIcons name="login" size={26} color="black" />
              ),
              headerLeftContainerStyle: { paddingLeft: 10 },
              headerRightContainerStyle: { paddingRight: 10 },
            }}
          />
        }
        
        <Tab.Screen name="Details" component={Blog_Info} />
      </Tab.Navigator>
      <StatusBar style="dark" />
    </NavigationContainer>
  );
}

CodePudding user response:

React navigation's bottomTab navigator has an "initialRoute" option. You could make it a different route depending on if the user is logged in or not.

CodePudding user response:

I ended up nesting two tab navigators in a stack navigator. One tab navigator is for logged-in users and the other is for users that aren't logged in.

The updated App.js:

import "react-native-gesture-handler";

import React, { useState } from "react";
import { Text } from "react-native";

import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createStackNavigator } from '@react-navigation/stack';

import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";

import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";

import { getGlobalState, setGlobalState } from "./src/GlobalState";

const LoggedOutTab = createBottomTabNavigator();
const LoggedInTab = createBottomTabNavigator();
const Stack = createStackNavigator();

function LoggedInTabNavigator() {
  return (
    <LoggedInTab.Navigator
      screenOptions={({ route }) => ({
        tabBarButton: route.name === "Details" ? () => null : undefined,
        tabBarIcon: ({ focused, color, size }) => {
          if (route.name === "Blogs") {
            return <Entypo name="text-document" size={size} color={color} />;
          } else if (route.name === "Post_Blog") {
            return <Entypo name="new-message" size={size} color={color} />;
          } else if (route.name === "Login") {
            return <SimpleLineIcons name="login" size={size} color={color} />;
          } else if (route.name === "Sign_Up") {
            return <Feather name="user-plus" size={size} color={color} />;
          } else if (route.name === "Logout") {
            return (
              <SimpleLineIcons name="logout" size={size} color={color} />
            );
          }
        },
        tabBarActiveTintColor: "tomato",
        tabBarInactiveTintColor: "gray",
      })}
    >
      <LoggedInTab.Screen
        name="Blogs"
        component={Blogs}
        initialParams={{ message: "" }}
        options={{
          headerLeft: (props) => (
            <Entypo name="text-document" size={26} color="black" />
          ),
          headerRight: (props) => (
            <Text style={{ fontSize: 16 }}>
              <Feather name="user" size={24} color="black" />
              User: {getGlobalState("username")}
            </Text>
          ),
          headerLeftContainerStyle: { paddingLeft: 10 },
          headerRightContainerStyle: { paddingRight: 10 },
        }}
      />

      <LoggedInTab.Screen
        name="Post_Blog"
        component={PostBlog}
        options={{
          headerLeft: (props) => (
            <Entypo name="new-message" size={26} color="black" />
          ),
          headerRight: (props) => (
            <Text style={{ fontSize: 16 }}>
              <Feather name="user" size={24} color="black" />
              User: {getGlobalState("username")}
            </Text>
          ),
          headerLeftContainerStyle: { paddingLeft: 10 },
          headerRightContainerStyle: { paddingRight: 10 },
        }}
      />

      <LoggedInTab.Screen name="Logout" component={Logout} />
      
      <LoggedInTab.Screen name="Details" component={Blog_Info} />
    </LoggedInTab.Navigator>
  );
}

function LoggedOutTabNavigator() {
  return (
    <LoggedOutTab.Navigator
      screenOptions={({ route }) => ({
        tabBarButton: route.name === "Details" ? () => null : undefined,
        tabBarIcon: ({ focused, color, size }) => {
          if (route.name === "Blogs") {
            return <Entypo name="text-document" size={size} color={color} />;
          } else if (route.name === "Post_Blog") {
            return <Entypo name="new-message" size={size} color={color} />;
          } else if (route.name === "Login") {
            return <SimpleLineIcons name="login" size={size} color={color} />;
          } else if (route.name === "Sign_Up") {
            return <Feather name="user-plus" size={size} color={color} />;
          } else if (route.name === "Logout") {
            return (
              <SimpleLineIcons name="logout" size={size} color={color} />
            );
          }
        },
        tabBarActiveTintColor: "tomato",
        tabBarInactiveTintColor: "gray",
      })}
    >
      <LoggedOutTab.Screen
        name="Blogs"
        component={Blogs}
        initialParams={{ message: "" }}
        options={{
          headerLeft: (props) => (
            <Entypo name="text-document" size={26} color="black" />
          ),
          headerRight: (props) => (
            <Text style={{ fontSize: 16 }}>
              <Feather name="user" size={24} color="black" />
              User: {getGlobalState("username")}
            </Text>
          ),
          headerLeftContainerStyle: { paddingLeft: 10 },
          headerRightContainerStyle: { paddingRight: 10 },
        }}
      />

      <LoggedOutTab.Screen
        name="Sign_Up"
        component={Sign_Up}
        options={{
          headerLeft: (props) => (
            <Feather name="user-plus" size={20} color="black" />
          ),
          headerRight: (props) => (
            <Text style={{ fontSize: 16 }}>
              <Feather name="user" size={24} color="black" />
              User: {getGlobalState("username")}
            </Text>
          ),
          headerLeftContainerStyle: { paddingLeft: 10 },
          headerRightContainerStyle: { paddingRight: 10 },
        }}
      />

      <LoggedOutTab.Screen
        name="Login"
        component={Login}
        options={{
          headerLeft: (props) => (
            <SimpleLineIcons name="login" size={26} color="black" />
          ),
          headerLeftContainerStyle: { paddingLeft: 10 },
          headerRightContainerStyle: { paddingRight: 10 },
        }}
      />
      
      <LoggedOutTab.Screen name="Details" component={Blog_Info} />
    </LoggedOutTab.Navigator>
  );
}


export default function App() {
  let [fontsLoaded] = useFonts({
    Recursive_300,
  });

  const [isChecking, setIsChecking] = useState(true);

  const [isSignedIn, setIsSignedIn] = useState(null);

  async function getUserData() {
    const username = await SecureStore.getItemAsync("blogger101_Username");
    const password = await SecureStore.getItemAsync("blogger101_Password");
    const email = await SecureStore.getItemAsync("blogger101_Email");
    setGlobalState("username", username);
    setGlobalState("password", password);
    setGlobalState("email", email);
    if (username === null) {
      setIsSignedIn(false);
    } else {
      setIsSignedIn(true);
    }
  }

  if (isChecking) {
    return (
      <AppLoading
        startAsync={getUserData}
        onFinish={() => setIsChecking(false)}
        one rror={console.warn}
      />
    );
  } else {
    if (getGlobalState("username") === null && isSignedIn !== false) {
      setIsSignedIn(false);
    } else if (getGlobalState("username") !== null && isSignedIn !== true) {
      setIsSignedIn(true);
    }
  }

  return (
    <NavigationContainer>
      <Stack.Navigator
        screenOptions={{
          headerShown: false
        }}
        initialRouteName={isSignedIn ? "LoggedIn" : "LoggedOut"}
      >
        <Stack.Screen
          name="LoggedIn"
          component={LoggedInTabNavigator}
        />
        <Stack.Screen
          name="LoggedOut"
          component={LoggedOutTabNavigator}
        />
      </Stack.Navigator>
      <StatusBar style="dark" />
    </NavigationContainer>
  );
}
  • Related