I'm building a React-Native app with Expo. I try to implement BottomTabNavigator, but for some reason the content (TripsPage) appears twice.
this is my Implementation of the navigation:
<NavigationContainer>
<Stack.Navigator
initialRouteName="TripsPage"
screenOptions={{
headerStyle: {
backgroundColor: Colors.primary,
},
headerTintColor: 'black',
headerTitleAlign: 'center',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 18,
},
}}
>
<Stack.Screen
name="TripDetails"
component={TripDetails}
options={{ title: 'Trip Details' }}
/>
<Stack.Screen
name="TripsPage"
component={TripsPage}
options={{ title: 'Home' }}
/>
<Stack.Screen
name="MVPForm"
component={Form}
options={{ title: 'Trippy' }}
/>
<Stack.Screen
name="Result"
component={Result}
options={{ title: 'Car Allocation' }}
/>
</Stack.Navigator>
</NavigationContainer>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={TripsPage} />
</Tab.Navigator>
</NavigationContainer>
Is anyone familiar with this issue?
Hello try using only one <NavigationContainer> and wrap all the navigators in that, like this:
<NavigationContainer>
<Stack.Navigator
initialRouteName="TripsPage"
screenOptions={{
headerStyle: {
backgroundColor: Colors.primary,
},
headerTintColor: 'black',
headerTitleAlign: 'center',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 18,
},
}}
>
<Stack.Screen
name="TripDetails"
component={TripDetails}
options={{ title: 'Trip Details' }}
/>
<Stack.Screen
name="TripsPage"
component={TripsPage}
options={{ title: 'Home' }}
/>
<Stack.Screen
name="MVPForm"
component={Form}
options={{ title: 'Trippy' }}
/>
<Stack.Screen
name="Result"
component={Result}
options={{ title: 'Car Allocation' }}
/>
</Stack.Navigator>
<Tab.Navigator>
<Tab.Screen name="Home" component={TripsPage} />
</Tab.Navigator>
</NavigationContainer>
Related
When navigating to a screen from my second bottom tab(tab2), the app switches to tab1 and then navigates to the screen. When you click on the text to change screens, you can see the tab1 screen flash right before it swipes to the page.
How can I stay on the tab I am navigating from? I want to navigate to screen3 while keeping the tab on tab2.
Why is it changing tabs upon navigation?
To reproduce the bug... Click Tab2 -> click the text -> and you can see the bottom tab switch and the tab1 screen flashing before going to screen3.
Here is a snack code reproducing my project exactly along with my app.js below.
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Stack.Navigator
initialRouteName="Home">
<Stack.Screen name="Home" component= {Home} options={{headerShown: false}}/>
<Stack.Screen name="Screen1" component= {Screen1} options={{headerShown: false}}/>
<Stack.Screen name="Screen2" component= {Screen2} options={{headerShown: false}}/>
<Stack.Screen name="Screen3" component= {Screen3} options={{headerShown: false}}/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
initialRouteName="Tab1"
screenOptions={{
tabBarActiveTintColor: 'white',
tabBarInactiveTintColor: '#4d4d4d',
tabBarStyle: {
backgroundColor: '#d1cfcf',
borderTopColor: 'transparent',
},
}}
>
<Tab.Screen
name="Tab1"
component={MyTabs}
options={{
tabBarLabel: 'Tab1',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Tab2"
component={Screen2}
options={{
tabBarLabel: 'Tab2',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
const Stack = createStackNavigator();
In your demo code, navigating to screen1 shows the bottomTabBar at the bottom, is this your required use case or a bug. I am assuming that it is bug and you don't want that.
To achieve that , it is recommended to use screens first and then BottomTabs. So define your bottomTabs in screen1 then your existing code works as you want it.
your App should return
<NavigationContainer>
<Stack.Navigator
initialRouteName="Tabs">
<Stack.Screen name="Tabs" component= {MyTabs} options={{headerShown: false}}/>
<Stack.Screen name="Screen1" component= {Screen1} options={{headerShown: false}}/>
<Stack.Screen name="Screen2" component= {Screen2} options={{headerShown: false}}/>
<Stack.Screen name="Screen3" component= {Screen3} options={{headerShown: false}}/>
</Stack.Navigator>
your MyTabs function should return
<Tab.Navigator
initialRouteName="Home"
screenOptions={{
tabBarActiveTintColor: 'white',
tabBarInactiveTintColor: '#4d4d4d',
tabBarStyle: {
backgroundColor: '#d1cfcf',
borderTopColor: 'transparent',
},
}}
>
<Tab.Screen
name="Home"
component={Home}
options={{
tabBarLabel: 'Tab1',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Tab2"
component={Screen2}
options={{
tabBarLabel: 'Tab2',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
Working snack code is here
Edit: for bottomTabs to be visible even after navigation, you should create another Stacknavigator as you did for Tab1.
your code should look something like this,
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen1"
component={Screen1}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen2"
component={Screen2}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen3"
component={Screen3}
options={{ headerShown: false }}
/>
</Stack.Navigator>
);
}
function MySecondTabs() {
return (
<Stack.Navigator initialRouteName="Screen2">
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen1"
component={Screen1}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen2"
component={Screen2}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen3"
component={Screen3}
options={{ headerShown: false }}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
initialRouteName="Tab1"
screenOptions={{
tabBarActiveTintColor: 'white',
tabBarInactiveTintColor: '#4d4d4d',
tabBarStyle: {
backgroundColor: '#d1cfcf',
borderTopColor: 'transparent',
},
}}>
<Tab.Screen
name="Tab1"
component={MyTabs}
options={{
tabBarLabel: 'Tab1',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Tab2"
component={MySecondTabs}
options={{
tabBarLabel: 'Tab2',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
working snack code
I make drawer.navigator that nested tab.navigator, Then show an icon that I didn't add to the code! and tried to remove it but couldn't...!! Does anybody have an idea?
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home">
{()=>
<Tab.Navigator screenOptions={{
***// I try this but didn't work.***
// tabBarIcon: ()=>{return null}
tabBarIcon: ({focused,color,size})=>
{
***// I do what in here???***
},
tabBarIconStyle:{
// I try this too but didn't work.
display: 'none',
},
tabBarStyle: {
borderTopColor: 'rgba(0, 0, 0, .2)',
},
tabBarLabelStyle: {
fontSize: 13,
// I use one of this then run code! one time I use two of this! but didn't
worked!!
textAlignVertical: 'center',
justifyContent: 'center',
},
tabBarLabelPosition: 'beside-icon'
}}
>
<Tab.Screen name="Todos"
options={{
headerShown: false,
}}>
{ ()=>
<Home
todos={todos}
pressHandler={pressHandler}
submitHandler={submitHandler}
/>}
</Tab.Screen>
<Tab.Screen name='CompleteTodos' options={{headerShown: false}}>
{()=>
<CompleteTodos
todos={todos}
pressHandler={pressHandler}
/>}
</Tab.Screen>
</Tab.Navigator>
}
</Drawer.Screen>
<Drawer.Screen name="About" component={About} />
<Drawer.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
</NavigationContainer>
with no options
with display: none. BUT THE LABEL DIDN't CENTERED!!
You can completely replace the tab component for a custom made by you.
As noted in the React Navigation docs:
tabBarButton: props => <TouchableOpacity {...props} />
You can find further information on how to fully customized your navigation here: https://reactnavigation.org/docs/bottom-tab-navigator
How can I change drawerActiveBackgroundColor in React Navigation 6 here is my code:
<Drawer.Navigator
screenOptions={{
drawerActiveBackgroundColor: "red",
}}
drawerContent={props => <DrawerContent {...props} />}>
<Drawer.Screen
options={{
drawerStyle: {
backgroundColor: '#c6cbef',
width: 240,
},
}}
name="Login"
component={Login}
options={{headerShown: false}}
/>
<Drawer.Screen
name="SignUp"
component={SignUp}
options={{headerShown: false}}
/>
</Drawer.Navigator>
Please use
activeTintColor: Color for the icon and label when the item is active.
inactiveTintColor: Color for the icon and label when the item is inactive.
activeBackgroundColor: Background color for item when it's active.
inactiveBackgroundColor: Background color for item when it's inactive.
You will find those options inside Drawer.Screen > options.. something like this:
<Drawer.Screen
options={{
headerShown: false,
drawerActiveBackgroundColor: 'transparent',
drawerActiveTintColor: 'white',
drawerInactiveTintColor: 'white',
}}
name="TabNavigator"
component={TabNavigator}
/>
I have a project with a Stack and bottomTab navigator and I want to redirect to a stack navigator page from the bottomTabNavigator
Here is the code for my project:
Routes.js i.e Stack Navigator
<UserContext.Provider value={{userDetails, setUserDetails}}>
<Stack.Navigator
headerMode="screen"
screenOptions={{
header: ({scene, previous, navigation}) => {
const {options} = scene.descriptor;
const title =
options.headerTitle !== undefined
? options.headerTitle
: options.title !== undefined
? options.title
: scene.route.name;
return <Header title={title} />;
},
}}>
{userDetails ? (
<>
<Stack.Screen
name="home"
options={{title: 'Home'}}
component={BottomTabNavigator}
/>
<Stack.Screen
name="library"
component={Library}
options={() => ({
headerTitle: 'My Library',
})}
/>
<Stack.Screen
name="bookDetails"
component={BookDetails}
options={{title: 'Book Details'}}
/>
<Stack.Screen
name="reviews"
component={AllReviews}
options={{headerTitle: 'View all Reviews'}}
/>
</>
) : (
<Stack.Screen name="Login" component={Login} />
)}
</Stack.Navigator>
</UserContext.Provider>
bottomTabNavigator.js:
<Tab.Navigator
tabBarOptions={{activeTintColor: 'green', style: {height: tabBarHeight}}}>
<Tab.Screen
name={'Home'}
component={Home}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="home" size={27} color={color} />
),
}}
/>
<Tab.Screen
name={'Search'}
component={Home}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="search1" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'My Library'}
component={Library}
options={{
tabBarIcon: ({color}) => {
return (
<View
style={{
position: 'absolute',
bottom: 7,
height: 65,
width: 65,
borderRadius: 65,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 0.37,
shadowRadius: 7.49,
elevation: 12,
}}>
<AntDesign name="book" size={40} color={'white'} />
</View>
);
},
}}
/>
<Tab.Screen
name={'Browse'}
component={Home}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="earth" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'More'}
component={More}
options={{
tabBarIcon: ({color}) => (
<Feather name="more-horizontal" size={30} color={color} />
),
}}
/>
</Tab.Navigator>
What I want to do is when I tap on My Library in the tabNavigator the headerTitle still says home, I want it to say ""
Here is how I tried to achieve this:
useLayoutEffect(() => {
navigation.setOptions({headerTitle: 'My Library'});
}, [navigation, route]);
Any help is appreciated
Thanks
I tried doing it automatically but I couldn't figure it out, but what I did was use my custom header component on each screen and hardcode the title of the screen, so the process may not be as efficient as letting react navigation do all the work, but it works fine for me
One workaround you can use is to hide the header in the Home Component of your Stack navigator. You can then create custom headers for each of the tab screens.
I have this navigator, I want to hide the header only from component = {PagRoutes} (pagRoutes is a tabNavigator)
I appreciate any help
export default function Routes() {
return (
<Stack.Navigator
initialRouteName='Login'
>
<Stack.Screen
name="Home"
component={PagRoutes}
options={{
title: 'Dashboard'
}}
/>
<Stack.Screen name="Login" component={Login}
options={{
headerTitleAlign: 'center',
title: 'Login',
}} />
<Stack.Screen name="Registro" component={Registro}
options={{
headerTitleAlign: 'center',
title: 'Registro',
}} />
</Stack.Navigator>
)
}
export default function PagRoutes() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Exercicios" component={Exercicios} />
</Tab.Navigator>
)
}
You can give extra config to the <Stack.Screen />. You're looking for the option: headerShown: none. I'd do something like this:
<Stack.Screen
name="Home"
component={PagRoutes}
options={{
title: 'Dashboard',
headerShown: none
}}
/>