I setup Bottom tab navigator in my react native app with typescript.
I have Home, Explore, Ticket and Profile screen in bottom tabs.
My Ticket screen is just showing a simple text, when i click on empty area on the screen it automatically redirecting back to home tab, same for other tabs.
**i'm developing on macOS
machin: macbook air
OS: macOS sonoma 14.4.1
memory: 8 GB
chip: apple M2
packages i use
"react-native": "0.74.2"
"react-navigation/bottom-tabs": "^6.5.20"
here is my code.
AppStack.tsx
import React from "react";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { AppStackParamList } from "@src/types";
import { SearchEvent } from "@src/screens";
import { BottomStack } from "./BottomStack";
import { EventDetails } from "@src/screens/event-detail/EventDetails";
import { useNavigationLogger } from "@src/hooks/useNavigationLogger";
const { Navigator, Screen } = createNativeStackNavigator<AppStackParamList>();
export function AppStack(): React.JSX.Element {
useNavigationLogger();
return (
<Navigator
screenOptions={{ headerShown: false }}
initialRouteName="BottomStack">
<Screen name="BottomStack" component={BottomStack} />
<Screen name="EventDetail" component={EventDetails} />
<Screen name="SearchEvent" component={SearchEvent} />
</Navigator>
);
}
BottomStack.tsx
import React from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { AppStackParamList } from "@src/types";
import { Home, Explore, Tickets, Profile } from "@src/screens";
import OcticonsHomeIcon from "react-native-vector-icons/Octicons";
import AntDesignSearchIcon from "react-native-vector-icons/AntDesign";
import MaterialCommunityIconsTicketIcon from "react-native-vector-icons/MaterialCommunityIcons";
import AntDesignProfileIcon from "react-native-vector-icons/AntDesign";
import { ViewStyle } from "react-native";
import { colors } from "@src/utils";
interface IconProps {
focused: boolean;
color: string;
size: number;
}
const HomeIcon: React.FC<IconProps> = ({ focused, color, size }) => (
<OcticonsHomeIcon
name={focused ? "home" : "home"}
size={size}
color={color}
/>
);
const SearchIcon: React.FC<IconProps> = ({ focused, color, size }) => (
<AntDesignSearchIcon
name={focused ? "search1" : "search1"}
size={size}
color={color}
/>
);
const TicketIcon: React.FC<IconProps> = ({ focused, color, size }) => (
<MaterialCommunityIconsTicketIcon
name={focused ? "ticket-confirmation" : "ticket-confirmation"}
size={size}
color={color}
/>
);
const ProfileIcon: React.FC<IconProps> = ({ focused, color, size }) => (
<AntDesignProfileIcon
name={focused ? "user" : "user"}
size={size}
color={color}
/>
);
const screenOptions = ({ route }: { route: any }) => ({
tabBarIcon: ({ focused, color, size }: IconProps) => {
switch (route.name) {
case "Home":
return <HomeIcon focused={focused} color={color} size={size} />;
case "Explore":
return <SearchIcon focused={focused} color={color} size={size} />;
case "Tickets":
return <TicketIcon focused={focused} color={color} size={size} />;
case "Profile":
return <ProfileIcon focused={focused} color={color} size={size} />;
default:
return null;
}
},
tabBarActiveTintColor: colors.primary,
tabBarInactiveTintColor: colors.textSecondary,
headerShown: false,
tabBarLabelStyle: {
fontSize: 12,
},
tabBarStyle: {
height: 60,
backgroundColor: colors.black,
justifyContent: "center",
borderTopWidth: 0,
} as ViewStyle,
});
const BottomTab = createBottomTabNavigator<AppStackParamList>();
export function BottomStack(): React.ReactElement {
return (
<BottomTab.Navigator initialRouteName="Home" screenOptions={screenOptions}>
<BottomTab.Screen name="Home" component={Home} />
<BottomTab.Screen name="Explore" component={Explore} />
<BottomTab.Screen name="Tickets" component={Tickets} />
<BottomTab.Screen name="Profile" component={Profile} />
</BottomTab.Navigator>
);
}
Tickets.tsx
import React from "react";
import { Text, View } from "react-native";
export function Tickets({}): React.JSX.Element {
console.log("Tickets screen rendered");
return (
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<Text>this is Tickets screen</Text>
</View>
);
}
Profile.tsx
import { Nf3Button } from "@src/components/common";
import React from "react";
import { Text, View } from "react-native";
import { useAppDispatch } from "@src/hooks";
import { logout } from "@src/store/slices/user-slice";
export function Profile({}): React.JSX.Element {
const dispatch = useAppDispatch();
return (
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<Text>this is profile screen</Text>
<Nf3Button
title="logout"
style={{ alignSelf: "center" }}
onPress={() => dispatch(logout())}
/>
</View>
);
}
i use a custom hook to log the navigation state change. this is the code of hook to logs the navigation state change.
useNavigationLogger.ts
import { useEffect } from "react";
import { useNavigation, useNavigationState } from "@react-navigation/native";
export function useNavigationLogger() {
const navigation = useNavigation();
const state = useNavigationState((state) => state);
useEffect(() => {
const unsubscribe = navigation.addListener("state", () => {
console.log("Navigation state changed:", JSON.stringify(state, null, 2));
});
return unsubscribe;
}, [navigation, state]);
}
when i open the app and navigate to Ticket screen it logs
LOG Tickets screen rendered
LOG Navigation state changed: undefined
then when i click on empty area of the Ticket screen then it logs
LOG Navigation state changed: {
"stale": false,
"type": "stack",
"key": "stack-mb5sp5e4a4kn9dj_0kHvK",
"index": 0,
"routeNames": [
"BottomStack",
"EventDetail",
"SearchEvent"
],
"routes": [
{
"key": "BottomStack-VQT1LwwFSP7qtfSF10J6h",
"name": "BottomStack",
"state": {
"stale": false,
"type": "tab",
"key": "tab-euFwrJf651_yFCB2jAHQJ",
"index": 2,
"routeNames": [
"Home",
"Explore",
"Tickets",
"Profile"
],
"history": [
{
"type": "route",
"key": "Home-qKX3M5AQ2M5H9ATqwSzi6"
},
{
"type": "route",
"key": "Tickets-X9PZhIsfM7R4O4HJtEfI_"
}
],
"routes": [
{
"name": "Home",
"key": "Home-qKX3M5AQ2M5H9ATqwSzi6"
},
{
"name": "Explore",
"key": "Explore-oxyMhsKyagZFlG5oXrFPM"
},
{
"name": "Tickets",
"key": "Tickets-X9PZhIsfM7R4O4HJtEfI_"
},
{
"name": "Profile",
"key": "Profile-5BhwfhOYgLMcFIFt-5Adq"
}
]
}
}
]
}```
so i don't know what was breaking but, i just uninstall the app, deleted node_modules, podfile, package-lock.json, cleaned the npm cache, installed pods rebuild the project from xcode it fix the wired issue.