I have an app that is composed of a tabbed navigation with 5 screens and one of them is a stack navigation of two screens. On one of the two stack screens I want to hide the bottom tabs. How can I do that ?
I already checked React Navigation V5 Hide Bottom Tabs but when I tried using navigation.setOptions({ tabBarVisible: false }) it changed the options for the stack navigator not the tab one.
Here is my code
// Screen where I want to hide the BottomTabNavigator
function StackSecondScreen({ navigation }) {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "indianred"
}}
>
<Text>StackSecondScreen</Text>
</View>
);
}
const Stack = createStackNavigator();
function TabFirstScreen({ navigation }) {
return (
<Stack.Navigator initialRouteName="StackFirst">
<Stack.Screen
name="StackFirst"
component={StackFirstScreen}
options={{
headerShown: false
}}
/>
<Stack.Screen name="StackSecond" component={StackSecondScreen} /> // <== Screen where I want to hide the BottomTabNavigator
</Stack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="First">
<Tab.Screen name="TabFirst" component={TabFirstScreen} />
<Tab.Screen name="TabSecond" component={TabSecondScreen} />
<Tab.Screen name="TabThird" component={TabThirdScreen} />
<Tab.Screen name="TabFourth" component={TabFourthScreen} />
<Tab.Screen name="TabFifth" component={TabFifthScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
Related
Tried these two ways, but none worked:
options={{
headerLeft: () => {
return null}
}}
// method 2
screenOptions={{
headerLeft: null,
}}
You could do it for all screens or for one of them like so:
<Stack.Navigator
// For all screens inside this Stack Navigator
screenOptions={{
headerBackVisible: false,
}}
>
<Stack.Screen
// For the login screen inside this Stack Navigator
options={{ headerBackVisible: false }}
component={LoginScreen}
name="Login"
/>
</Stack.Navigator>
White flicker when switching from bottom tab navigator to top tab navigator
This white flicker is much more noticeable outside of this gif. But I am using an Expo managed React Native project and when I switch from my Bottom tab navigator to my Top tab navigator the screen flickers white. This issue only occurs on Android. On top of that, when you press a TextInput to open the keyboard, the screen turns white in the section the keyboard takes up while the keyboard animation is occuring. Here are my navigators in App.js
const AuthTabs = createMaterialTopTabNavigator();
const AuthStackScreen = () => (
<AuthTabs.Navigator tabBarOptions={options}>
<AuthTabs.Screen name="Sign In" component={SignInScreen} />
<AuthTabs.Screen name="Sign Up" component={SignUpScreen} />
</AuthTabs.Navigator>
);
const Tab = createBottomTabNavigator();
const MainStack = () => (
<Tab.Navigator>
<Tab.Screen name="Deals" component={DealsStackScreen} />
<Tab.Screen name="Categories" component={CategoriesStackScreen} />
<Tab.Screen name="My Account" component={MyAccountStackScreen} />
</Tab.Navigator>
const RootStack = createStackNavigator();
const Root = () => (
<RootStack.Navigator headerMode="none" cardStyle={{opacity: 1}} >
<RootStack.Screen name="Home" component={MainStack}/>
<RootStack.Screen name="Auth" component={AuthStackScreen}/>
</RootStack.Navigator>
);
return (
<AuthContextProvider>
<NavigationContainer theme={{ colors: {background: `${Colors.surface}` }}}>
<Root />
</NavigationContainer>
</AuthContextProvider>
);
I tried adding my theme color to the NavigationContainer but this did not fix the issue. Also link shows the GIF of what is happening.
Yes, you have to wrap your RootStack around a View with backgroundColor as theme's backgroundColor
Your RootStack would look something like this now
import { useTheme } from '#react-navigation/native';
...
const { colors } = useTheme();
const RootStack = createStackNavigator();
const Root = () => (
<View style={{ flex:1, backgroundColor: colors.background }}> // This is the catch..Also it needs flex:1
<RootStack.Navigator headerMode="none" cardStyle={{ opacity: 1 }}>
<RootStack.Screen name="Home" component={MainStack} />
<RootStack.Screen name="Auth" component={AuthStackScreen} />
</RootStack.Navigator>
</View>
);
I am trying to use the navigation prop inside my Stack Navigator to open the drawer when the material icon is clicked. However when I click th button I recieve the error:
Undefined is not an object (evaluating navigation.openDrawer)
I am confused as I have passed the navigation prop into the 'App' function. Where am I going wrong here?
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createDrawerNavigator} from '#react-navigation/drawer';
import HomeScreen from './src/screens/HomeScreen';
import SecondScreen from './src/screens/SecondScreen.js';
import {MaterialIcons} from '#expo/vector-icons';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const TheDrawer = () => {
return(
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="SecondScreen" component={SecondScreen} />
</Drawer.Navigator>
);
}
const App = ({navigation}) =>{
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"component={TheDrawer}
options={{headerTitle:
<View>
<MaterialIcons
name='menu'
onPress={() => navigation.openDrawer()} size={28}
/>
</View>
}}
/>
<Stack.Screen name="SecondScreen" component={SecondScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default App;
The navigation prop only exist inside a Navigator, and different Navigators will have different navigation props (the Stack Navigator navigation will NOT have the openDrawer method, for example). I think that what you want to accomplish is this:
const App = () => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen
name="Home"
component={HomeScreen}
options={({ navigation }) => ({
headerTitle: (
<View>
<MaterialIcons name="menu" onPress={() => navigation.openDrawer()} size={28}/>
</View>
),
})}
/>
<Drawer.Screen name="SecondScreen" component={SecondScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
};
Or, if you want the menu button available on every page header:
const App = () => {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Home"
screenOptions={({ navigation }) => ({
headerTitle: (
<View>
<MaterialIcons name="menu" onPress={() => navigation.openDrawer()} size={28} />
</View>
),
})}
>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="SecondScreen" component={SecondScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
};
Source: https://reactnavigation.org/docs/headers/
If you need to access more pages inside this two (Home, SecondScreen), you can create it like this:
const HomeScreen = () => {
<Stack.Navigator>
<Stack.Screen name="Home1" component={HomeScreen1} />
<Stack.Screen name="Home2" component={HomeScreen2} />
<Stack.Screen name="Home3" component={HomeScreen3} />
</Stack.Navigator>
}
Source: https://reactnavigation.org/docs/nesting-navigators
I want to show a back button in the header of a screen that is nested in 2 navigators.
I will first show you how I am nesting the screen, followed by what I have tried
Main stack navigator:
<Provider store = {store}>
<StatusBar style="light" />
<NavigationContainer>
<Stack.Navigator initialRouteName="Login">
<Stack.Screen name="Login"
component={Login}
options= {{
headerLeft: null,
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212'
}
}}/>
<Stack.Screen
name="Tabs"
component={Tabs} <-------------- The screen is nested in tabs
options= {{
title: " ",
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 24,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212'
},
}}/>
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
}
Tab navigator, nested within the stack navigator as "Tabs":
//Bottom Tabs
function Tabs() {
return (
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor:"#FFFFFF",
inactiveTintColor:"#696969",
style: {
backgroundColor: '#000000'
},
}}>
<Tab.Screen
name="Create"
component={createFlowStack} <------------ This stack is where the screen header I want to add a back button to lies
options={{
tabBarLabel: ' ',
tabBarIcon: ({ color, size }) => (
<Ionicons name="md-add-circle" size={size} color={color} />
),
}}
/>
</Tab.Navigator>
);
}
I have deleted the other tabs as they are not relevant to the question. This tab, create, is nesting another stack navigator, createFlowStack:
createFlowStack, which is shown when you click on the bottom tab "create"
<CreateStack.Navigator
initialRouteName="Create"
>
<CreateStack.Screen
name="Create"
component={Create} />
<CreateStack.Screen
name="Screenshot"
component={Screenshot}
// options={({ navigation }) => ({
// headerRight: () => (
// <Button
// onPress={() => navigation.goBack()}
// title="Info"
// color="#fff" />
// ),
// })}
/>
As you can see, the options are commented out, but it wouldn't matter any way. I am trying to show a back button in header left of this screen, but nothing I have tried works.
What I have tried:
headerBackTitle: "back"
headerBackTitle: " "
A custom header left button
headerRight: " "
The custom header right button you see commented out
NOTHING works, nothing shows up, its like one of the navigators that createFlowStack is nested in is overriding everything. Please let me know how to fix this issue!
Updating the expo SDK from 39 to 40 fixed the issue!
I'm using the drawer navigation from React Navigation v5. In my root file i've created the drawer navigator. Some of the screens inside of this navigator has a nested stack navigator. The first item is dashboard and the second item is Relations.
The problem is when I go to relations I don't get a back button for going to the first screen (Dashboard). Is it possible to add this to my relations screen?
Root code:
<NavigationContainer>
<DrawerNavigator.Navigator
drawerContent={(props) => (
<SidebarComponent {...props} user={this.props.device.user} />
)}
drawerPosition="right"
drawerStyle={{width: '90%', padding: 0, backgroundColor: 'red'}}>
{this.props.authenticated && this.props.device.api_key ? (
<>
<DrawerNavigator.Screen
name="Home"
options={{
headerShown: false,
icon: 'tachometer-alt',
category: 'dashboard',
}}
component={DashboardStack}
/>
<DrawerNavigator.Screen
name="Relations"
options={{
icon: 'address-book',
category: 'dashboard',
}}
component={RelationsStack}
/>
</>
) : (
<>
<DrawerNavigator.Screen
name="login"
options={{headerShown: false, gestureEnabled: false}}
component={LoginStack}
/>
</>
)}
</DrawerNavigator.Navigator>
</NavigationContainer>
Relation stack code:
import 'react-native-gesture-handler';
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import RelationsListScreen from '../RelationsListScreen';
import {colors} from '../../../assets/styles/variables';
const Stack = createStackNavigator();
function RelationsStack() {
return (
<Stack.Navigator>
<Stack.Screen
options={{
headerShown: true,
headerTintColor: '#FFF',
headerStyle: {
backgroundColor: colors.primary,
shadowColor: 'transparent',
},
}}
name="Relations"
component={RelationsListScreen}
/>
</Stack.Navigator>
);
}
export default RelationsStack;
You could create a stack navigator that is a screen of your drawer navigator (when the user is authenticated) which has Home and Relations as screens. I've called this navigator AuthenticatedNavigator in the example below:
const AuthenticatedStack = createStackNavigator();
// ...
const AuthenticatedNavigator = () => {
return (
<AuthenticatedStack.Navigator screenOptions={{headerShown: false}}>
<AuthenticatedStack.Screen
name="Home"
options={{
icon: 'tachometer-alt',
category: 'dashboard',
}}
component={DashboardStack}
/>
<AuthenticatedStack.Screen
name="Relations"
options={{
icon: 'address-book',
category: 'dashboard',
}}
component={RelationsStack}
/>
</AuthenticatedStack.Navigator>
);
};
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
<DrawerItem
label="Relations"
onPress={() => props.navigation.navigate('Relations')}
/>
</DrawerContentScrollView>
);
}
function App() {
const authenticated = true;
return (
<NavigationContainer>
<DrawerNavigator.Navigator
drawerPosition="right"
drawerStyle={{width: '90%', padding: 0, backgroundColor: 'red'}}
drawerContent={(props) => <CustomDrawerContent {...props} />}>
{authenticated ? (
<DrawerNavigator.Screen
name="authenticated"
component={AuthenticatedNavigator}
/>
) : (
<DrawerNavigator.Screen
name="login"
options={{headerShown: false, gestureEnabled: false}}
component={LoginStack}
/>
)}
</DrawerNavigator.Navigator>
</NavigationContainer>
);
}
I've also used a custom drawer content component so the links in the drawer still work correctly after using the approach of creating another stack navigator. You can read more about providing a custom drawer component in the documentation here: https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.
I've left out some code and made authenticated a hardcoded value to simplify the example. Also be sure to import DrawerItem, DrawerContentScrollView from #react-navigation/drawer.