1

I am very new to React Navigation and am trying to implement the following functionality in react-native: I have a stack navigator as a parent and a bottom navigation bar as its child. From the home screen, when the user clicks the logout option, they should return to the Sign In screen which is a part of the parent navigation.

There are already a lot of questions regarding this, but I am not able to implement the previous solutions in my code.

Someone please help me out, the code is given below (This is an Expo managed project):

Navigation Components

import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import WelcomeScreen from "../screens/WelcomeScreen";
import Features from "../screens/Features";
import SignIn from "../screens/SignIn";
import Register from "../screens/Register";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Icon } from "react-native-elements";
import Home from "../screens/Home";
import Reminders from "../screens/Reminders";
import Settings from "../screens/Settings";

const BottomNavbar = () => {
    const Tab = createBottomTabNavigator();
    return (
        <Tab.Navigator
            initialRouteName="Home"
            screenOptions={({ route }) => ({
                tabBarIcon: ({ focused }) => {
                    let iconName;
                    let rn = route.name;
                    if (rn === "Home") {
                        iconName = focused ? "home" : "home-outline";
                    } else if (rn === "Reminders") {
                        iconName = focused ? "list" : "list-outline";
                    } else if (rn === "Settings") {
                        iconName = focused ? "settings" : "settings-outline";
                    }
                    return (
                        <Icon
                            name={iconName}
                            size={25}
                            color="black"
                            type="ionicon"
                        />
                    );
                },
            })}
            showLabel
        >
            <Tab.Screen
                name="Home"
                component={Home}
                options={{ headerShown: false }}
            />
            <Tab.Screen
                name="Reminders"
                component={Reminders}
                options={{ headerShown: false }}
            />
            <Tab.Screen
                name="Settings"
                component={Settings}
                options={{ headerShown: false }}
            />
        </Tab.Navigator>
    );
};

const Navigator = () => {
    const Stack = createNativeStackNavigator();

    return (
        <NavigationContainer>
            <Stack.Navigator
                screenOptions={{ headerShown: false }}
                initialRouteName="Welcome"
            >
                <Stack.Screen name="Welcome" component={WelcomeScreen} />
                <Stack.Screen name="Features" component={Features} />
                <Stack.Screen name="SignIn" component={SignIn} />
                <Stack.Screen name="Register" component={Register} />
                <Stack.Screen name="BottomNavbar" component={BottomNavbar} />
            </Stack.Navigator>
        </NavigationContainer>
    );
};

export default Navigator;

Home Screen Components

import {
    View,
    Text,
    SafeAreaView,
    StyleSheet,
    TouchableOpacity,
    ScrollView,
} from "react-native";
import React from "react";
import { Header, Image, Icon } from "react-native-elements";
import { useFonts } from "expo-font";
import ServiceCard from "../components/ServiceCard";
import PetCard from "../components/PetCard";

const SignOut = ({ navigation }) => {
    return (
        <TouchableOpacity
            onPress={() => {
                navigation.navigate("SignIn");
            }}
        >
            <Icon name="logout" color="black" size={20} />
        </TouchableOpacity>
    );
};

const Home = () => {
    const [loaded, error] = useFonts({
        Montserrat: require("../assets/fonts/Montserrat-Regular.ttf"),
    });
    if (!loaded) {
        return null;
    }
    const url1 =
        "https://images.unsplash.com/photo-1530281700549-e82e7bf110d6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=388&q=80";
    const url2 =
        "https://images.unsplash.com/photo-1560807707-8cc77767d783?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80";
    const url3 =
        "https://images.unsplash.com/photo-1543466835-00a7907e9de1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80";
    return (
        <View style={styles.screen}>
            <Header
                leftComponent={{
                    icon: "menu",
                    color: "black",
                }}
                rightComponent={<SignOut />}
                centerComponent={{
                    text: "PetPapa",
                    color: "black",
                    style: {
                        fontFamily: "Montserrat",
                        fontSize: 20,
                    },
                }}
                barStyle="dark-content"
                backgroundColor="white"
                containerStyle={styles.header}
            />
            <View style={styles.community}>
                <View style={styles.commOffer}>
                    <View>
                        <Text style={styles.commOfferTitle}>Join our</Text>
                        <Text style={styles.commOfferTitle}>
                            community today!
                        </Text>
                    </View>
                    <TouchableOpacity style={styles.btn}>
                        <Text style={styles.commOfferJoin}>Join Now</Text>
                    </TouchableOpacity>
                </View>
                <Image
                    source={{
                        uri: "https://imgur.com/nB4Xm1Z.png",
                    }}
                    style={styles.commDog}
                />
            </View>
            <View style={styles.listView}>
                <View style={styles.topText}>
                    <Text style={styles.title}>Services</Text>
                    <TouchableOpacity>
                        <Text style={styles.option}>See more</Text>
                    </TouchableOpacity>
                </View>
                <ServiceCard />
            </View>
            <View style={styles.listView}>
                <View style={styles.topText}>
                    <Text style={styles.title}>My Pets</Text>
                    <TouchableOpacity>
                        <Text style={styles.option}>See all</Text>
                    </TouchableOpacity>
                </View>
                <ScrollView
                    style={styles.petView}
                    horizontal={true}
                    showsHorizontalScrollIndicator={true}
                    persistentScrollbar={true}
                >
                    <PetCard name="Miles" Img={url1} />
                    <PetCard name="Jack" Img={url2} />
                    <PetCard name="Ellie" Img={url3} />
                </ScrollView>
            </View>
        </View>
    );
};

const styles = StyleSheet.create({
    screen: {
        height: "100%",
        backgroundColor: "white",
        alignItems: "center",
    },
    header: {
        backgroundColor: "white",
        height: 80,
    },
    community: {
        backgroundColor: "#1976D2",
        height: "15%",
        width: "80%",
        borderRadius: 20,
        marginTop: 50,
        flexDirection: "row",
        justifyContent: "space-around",
    },
    commDog: {
        marginTop: 10,
        marginRight: 15,
        height: 105,
        width: 75,
    },
    commOffer: {
        marginTop: 10,
        flexDirection: "column",
        justifyContent: "space-around",
    },
    commOfferTitle: {
        color: "white",
        fontFamily: "Montserrat",
        fontSize: 16,
    },
    btn: {
        backgroundColor: "#FFC107",
        width: "50%",
        borderRadius: 10,
    },
    commOfferJoin: {
        color: "white",
        margin: 5,
    },
    listView: {
        marginTop: 50,
        width: "80%",
    },
    topText: {
        flexDirection: "row",
        justifyContent: "space-between",
        alignItems: "center",
    },
    title: {
        fontFamily: "Montserrat",
        fontWeight: "600",
    },
    option: {
        fontFamily: "Montserrat",
        opacity: 0.4,
    },
    block: {
        backgroundColor: "#FF5677",
        width: 75,
        height: 100,
        justifyContent: "center",
        alignItems: "center",
        marginTop: 25,
        borderRadius: 20,
    },
    petView: {
        width: "100%",
        backgroundColor: "white",
        height: 250,
    },
});
export default Home;

My Directory Structure:

Directory Structure for project

1 Answer 1

1

First you need to add navigation prop to Home screen component

const Home = ({navigation}) => {
    const [loaded, error] = useFonts({
        Montserrat: require("../assets/fonts/Montserrat-Regular.ttf"),
    });
   ...

then You need to pass navigation prop to the signout component

 <Header
    leftComponent={{
       icon: "menu",
       color: "black",
    }}
    rightComponent={<SignOut navigation={navigation} />}
    ...

You can also use useNavigation hook from react navigation

import { useNavigation } from '@react-navigation/native';

const SignOut = ({}) => {
    const navigation = useNavigation()
    return (
        <TouchableOpacity
            onPress={() => {
                navigation.navigate("SignIn");
            }}
        >
            <Icon name="logout" color="black" size={20} />
        </TouchableOpacity>
    );
};

If You want to create login flow then you should use Authentication flow which I think best prectice and recommended way

The problem in current flow if you logout and navigate to sign-in page once then if you navigate back from you app then as behaviour of stack navigation it just pop current screen and it will again navigate to home screen which is not what supposed to be correct.

You can learn it from react-navigation offical doc https://reactnavigation.org/docs/auth-flow/

if you want a video tutorial how to implement Authentication flow using redux(state management lib) then I have video tutorial you can learn this video -> https://youtu.be/cm1oJ7JmW6c

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.