I have recently started working with react native and I am using the latest version of react-navigation (v.5) in my react-native application. However, I encountered errors when trying to use createStackNavigator and createBottomTabNavigator together within NavigationContainer. The errors include "undefined is not an object" and "Another navigator is already registered for this container. You likely have multiple navigators under a single 'NavigationContainer' or 'Screen'. Make sure each navigator is under a separate 'Screen' container." This issue occurred specifically in React Navigation v.5. Can someone please guide me on what I am doing wrong?
AppNavigation.tsx
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { MainScreen } from "../screens/MainScreen";
import { PostScreen } from "../screens/PostScreen";
import { AboutScreen } from "../screens/AboutScreen";
import { BookedScreen } from "../screens/BookedScreen";
import { CreateScreen } from "../screens/CreateScreen";
import { THEME } from "../theme";
import { Platform } from "react-native";
import { AppHeaderIcon } from "../components/AppHeaderIcon";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
type RootStackParamList = {
Main: undefined;
Post: { postId?: string; date?: string; booked?: boolean };
About: undefined;
Booked: undefined;
Create: undefined;
};
const headerButtons = (title: string, icon: string, callback: () => void) => {
return (
<HeaderButtons HeaderButtonComponent={AppHeaderIcon}>
<Item title={title} iconName={icon} onPress={() => callback()} />
</HeaderButtons>
);
};
export const AppNavigation = () => {
const Stack = createStackNavigator<RootStackParamList>();
const Tab = createBottomTabNavigator();
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Main"
screenOptions={{
headerTintColor:
Platform.OS === "android" ? "white" : THEME.MAIN_COLOR,
headerStyle: {
backgroundColor:
Platform.OS === "android" ? THEME.MAIN_COLOR : "white"
}
}}
>
<Stack.Screen
name="Main"
component={MainScreen}
options={{
headerTitle: "My Blog",
headerRight: () =>
headerButtons("Take Photo", "ios-camera", () =>
console.log("Press camera")
),
headerLeft: () =>
headerButtons("drawer", "ios-menu", () =>
console.log("Press drawer button")
)
}}
/>
<Stack.Screen
name="Post"
component={PostScreen}
options={({ route }) => ({
headerTitle: `Post from ${new Date(
route.params.date
).toLocaleDateString()}`,
headerRight: () =>
headerButtons(
"star",
route.params.booked ? "ios-star" : "ios-star-outline",
() => console.log("Press star button")
)
})}
/>
<Stack.Screen name="About" component={AboutScreen} />
<Stack.Screen name="Booked" component={BookedScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
</Stack.Navigator>
<Tab.Navigator>
<Tab.Screen name="Post" component={PostScreen} />
<Tab.Screen name="Booked" component={BookedScreen} />
</Tab.Navigator>
</NavigationContainer>
);
};
App.tsx
import React, { useState } from "react";
import { AppLoading } from "expo";
import { bootstrap } from "./src/bootstrap";
import { AppNavigation } from "./src/navigation/AppNavigation";
export default function App() {
const [isReady, setIsReady] = useState(false);
if (!isReady) {
//AppLoading - until the code execution finishes, it will not proceed further
return (
<AppLoading
startAsync={bootstrap}
onFinish={() => setIsReady(true)}
onError={err => console.log('AppLoading error - ', err)}
/>
);
}
return <AppNavigation />;
}