I have this combineNavigator component
const CombineNavigation = () => {
const Drawer = createDrawerNavigator();
return (
<Drawer.Navigator>
<Drawer.Screen
key="general"
name="Home"
component={MainNavigator}
/>
<Drawer.Screen
key="cit"
name="quotes"
/>
<Drawer.Screen
key="cont"
name="Contact"
/>
</Drawer.Navigator>
);
};
In MainNavigator I have this
I have this
const MainNavigator = () => {
return (
<Stack.Navigator
<Stack.Screen
name="Français"
component={SFrench}
options={({navigation, route}) => ({
headerRight: () => {
return (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<CustomItem
iconName="menu"
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
</HeaderButtons>
);
},
})}
/>
</Stack.Navigator>
and the SFrench is also a drawer. However when I click on the headerRight of it opens the Combine navigation drawer instead of SFrench drawer. How can I fix that?
Related
I am trying to have a tab bar and each tab bar has its own stack navigator. Three tabs that i have are
Home
Profile
Settings
I want to show these three options in the drawer also. I have created a drawer but only tapping home shows the tab bar. I want to show tab bar just like if you press of profile tab and tab bar remains there.
Here is my code:
const HomeStackNavigator = createStackNavigator();
export const HomeNavigator = () => {
return (
<HomeStackNavigator.Navigator screenOptions={defaultNavOptions}>
<HomeStackNavigator.Screen
name="Home"
component={HomeScreen}
options={homeScreenOptions}
/>
<HomeStackNavigator.Screen
name="Details"
component={DetailsScreen}
options={detailsScreenOptions}
/>
</HomeStackNavigator.Navigator>
);
};
const ProfileStackNavigator = createStackNavigator();
export const ProfileNavigator = () => {
return (
<ProfileStackNavigator.Navigator screenOptions={defaultNavOptions}>
<ProfileStackNavigator.Screen
name="Profile"
component={ProfileScreen}
options={profileScreenOptions}
/>
<ProfileStackNavigator.Screen
name="EditProfile"
component={EditProfileScreen}
options={editProfileScreenOptions}
/>
</ProfileStackNavigator.Navigator>
);
};
const SettingsStackNavigator = createStackNavigator();
export const SettingsNavigator = () => {
return (
<SettingsStackNavigator.Navigator screenOptions={defaultNavOptions}>
<SettingsStackNavigator.Screen
name="Settings"
component={SettingsScreen}
options={settingsScreenOptions}
/>
<SettingsStackNavigator.Screen
name="AccountDetail"
component={AccountDetailsScreen}
options={accountDetailsScreenOptions}
/>
</SettingsStackNavigator.Navigator>
);
};
const HomeTabNavigator = createBottomTabNavigator();
export const TabNavigator = () => {
return (
<HomeTabNavigator.Navigator screenOptions={defaultNavOptions}>
<HomeTabNavigator.Screen
name="Home"
component={HomeNavigator}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<HomeTabNavigator.Screen
name="Profile"
component={ProfileNavigator}
options={{
tabBarLabel: 'Profile',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="face-profile" color={color} size={size} />
),
}}
/>
<HomeTabNavigator.Screen
name="Settings"
component={SettingsNavigator}
options={{
tabBarLabel: 'Settings',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account-settings" color={color} size={size} />
),
}}
/>
</HomeTabNavigator.Navigator>
);
};
const AppDrawer = createDrawerNavigator();
export const Drawer = () => {
return(
<AppDrawer.Navigator initialRouteName="Home">
<AppDrawer.Screen name="Home" component={TabNavigator} />
<AppDrawer.Screen name="Profile" component={ProfileNavigator} />
<AppDrawer.Screen name="Settings" component={SettingsNavigator} />
</AppDrawer.Navigator>
)
};
My goal is to have tabs all the time. Tabs should hide only if we go to the detail page of any of the tabs.
You can make your TabNavigator a screen of a stack navigator which is a screen of your drawer navigator and pass a custom drawer component to your drawer navigator:
const AppDrawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
const HomeTabNavigator = createBottomTabNavigator();
export const TabNavigator = () => {
return (
<HomeTabNavigator.Navigator>
<HomeTabNavigator.Screen
name="Home"
component={HomeScreen}
options={{
tabBarLabel: 'Home',
}}
/>
<HomeTabNavigator.Screen
name="Profile"
component={ProfileScreen}
options={{
tabBarLabel: 'Profile',
}}
/>
<HomeTabNavigator.Screen
name="Settings"
component={SettingsScreen}
options={{
tabBarLabel: 'Settings',
}}
/>
</HomeTabNavigator.Navigator>
);
};
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
<DrawerItem
label="Profile"
onPress={() => props.navigation.navigate('Profile')}
/>
<DrawerItem
label="Settings"
onPress={() => props.navigation.navigate('Settings')}
/>
</DrawerContentScrollView>
);
}
function getHeaderTitle(route) {
return getFocusedRouteNameFromRoute(route) ?? 'Home';
}
const StackNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Tabs"
component={TabNavigator}
options={({route}) => ({
headerTitle: getHeaderTitle(route),
})}
/>
<Stack.Screen name="EditProfile" component={EditProfileScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
<Stack.Screen name="AccountDetail" component={AccountDetailsScreen} />
</Stack.Navigator>
);
};
export const Drawer = () => {
return (
<AppDrawer.Navigator
initialRouteName="Home"
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<AppDrawer.Screen name="Stack" component={StackNavigator} />
</AppDrawer.Navigator>
);
};
function App() {
return (
<NavigationContainer>
<Drawer />
</NavigationContainer>
);
}
The screens you don't want to show the tabs for can be put inside the stack navigator outside of the tab navigator.
Sources:
https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.
https://reactnavigation.org/docs/screen-options-resolution/#setting-parent-screen-options-based-on-child-navigators-state.
Be sure to import DrawerItem, DrawerContentScrollView from #react-navigation/drawer and getFocusedRouteNameFromRoute from #react-navigation/native.
Stack navigation is parent and tab navigation is child
I want to hide the button when I press the "settings" tab.
using `react-navigation ver.5
please help me.
child
const Tab = createBottomTabNavigator();
const Tabs = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Observatory" component={Observatory} />
<Tab.Screen name="Search" component={Search} />
<Tab.Screen name="Setting" component={Setting} />
</Tab.Navigator>
);
}
parent
const Stack = createStackNavigator();
export default App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Tabs"
component={Tabs}
options={({ navigation, route }) => ({
headerRight: () => (
<Icon
name="edit"
size={30}
color="#000"
onPress={() => navigation.navigate('Template')}
/>
),
})}
/>
<Stack.Screen name="Template" component={Template} />
</Stack.Navigator>
</NavigationContainer>
);
}
Getting the following Issue when I use Drawer. Stack and Tab are working fine without Drawer.
Does anyone know what is going on here and can help me?
enter image description here
Here is Navigator File some Code lines:
const Stack = createStackNavigator();
const FavStack = createStackNavigator();
const FilterStack = createStackNavigator();
const Tab =
Platform.OS === "android"
? createMaterialBottomTabNavigator()
: createBottomTabNavigator();
const defaultScreenOptions = {
headerStyle: { backgroundColor: colors.primary },
headerTintColor: "white",
};
function MealsNavigator() {
return (
<Stack.Navigator screenOptions={defaultScreenOptions}>
<Stack.Screen name="Meals Categories" component={CategoriesScreen} />
<Stack.Screen name="Profile" component={CategoryMealScreen} />
<Stack.Screen name="Details" component={MealDetailsScreen} />
</Stack.Navigator>
);
}
function FavStackNavigator() {
return (
<FavStack.Navigator screenOptions={defaultScreenOptions}>
<FavStack.Screen name="Favourites" component={FavouritesScreen} />
<FavStack.Screen name="Details" component={MealDetailsScreen} />
</FavStack.Navigator>
);
}
function MealsFavTabNavigator() {
return (
<Tab.Navigator
tabBarOptions={{ activeTintColor: colors.accent }}
shifting={true}
>
<Tab.Screen
name="All"
component={MealsNavigator}
options={{
tabBarLabel: "Meals",
tabBarIcon: (tabInfo) => (
<Ionicons name="ios-restaurant" size={25} color={tabInfo.color} />
),
tabBarColor: colors.primary,
}}
/>
<Tab.Screen
name="Favourites"
component={FavStackNavigator}
options={{
tabBarIcon: (tabInfo) => (
<Ionicons name="ios-star" size={25} color={tabInfo.color} />
),
tabBarColor: colors.accent,
}}
/>
</Tab.Navigator>
);
}
function FilterStackNavigator() {
return (
<FilterStack.Navigator>
<FilterStack.Screen name="Filters" component={FilterScreen} />
</FilterStack.Navigator>
);
}
const Drawer = createDrawerNavigator();
function MenuNavigator() {
return (
<Drawer.Navigator>
<Drawer.Screen name="MealFavs" component={MealsFavTabNavigator} />
<Drawer.Screen name="Filters" component={FilterStackNavigator} />
</Drawer.Navigator>
);
}
export default MenuNavigator;
Here is App.js few Code lines:
export default function App() {
const [fontLoaded, setFontLoaded] = useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setFontLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
return <NavigationContainer><MealsNavigator /></NavigationContainer>
}
Code is not giving error without Drawer, It is working exactly fine with Stack and Tab Navigators!
In my navigation file , when I want to toggle drawer , get the following error :
TypeError: navigation.openDrawer is not a function.(In
'navigation.openDrawer()', 'navigation.openDrawer' is undefined)
This is my drawer:
const DrawerNavigator = () => {
return (
<Drawer.Navigator
initialRouteName="MYSHIFT"
>
<Drawer.Screen name="MYSHIFT" component={TopTabNavigator} />
</Drawer.Navigator>
)
}
And this is my container navigation :
const CareworkerNavigation = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }} />
<Stack.Screen
name="Main"
options={({ navigation }) => {
return {
headerLeft: () => <Button title="LEFT BUTTON" onPress={() => {
navigation.toggleDrawer(); // <--- this line throws an error
}} />
}
}}
component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default CareworkerNavigation
Why I can not use navigation.toggleDrawer() in navigation options?
Is is possible to remove this problem ?
If you check the React Navigation docs, "You will need to make the drawer navigator the parent of any navigator where the drawer should be rendered on top of its UI."
React Navigation docs reference
To answer your question : Yes , it is possible.
And here you have a working example:
import React from 'react'
import { Button, View } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import { createDrawerNavigator } from '#react-navigation/drawer'
import { createStackNavigator } from '#react-navigation/stack'
const Feed = () => <View />
const Notifications = () => <View />
const Profile = () => <View />
const FeedStack = createStackNavigator()
const Home = ({ navigation }) => (
<FeedStack.Navigator>
<FeedStack.Screen
name="Feed"
component={Feed}
options={props => {
const { toggleDrawer } = props.navigation // <-- drawer's navigation (not from stack)
return {
headerLeft: () => <Button title="LEFT BUTTON" onPress={toggleDrawer} />
}
}}
/>
</FeedStack.Navigator>
)
const Drawer = createDrawerNavigator()
export default props => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Feed">
<Drawer.Screen
name="Feed"
component={Home}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Notifications"
component={Notifications}
options={{ drawerLabel: 'Updates' }}
/>
<Drawer.Screen
name="Profile"
component={Profile}
options={{ drawerLabel: 'Profile' }}
/>
</Drawer.Navigator>
</NavigationContainer>
)
}
While constructing navigation at options, you refer to the navigation of the stack, what cant perform draw actions, try to construct it on header itself
<Stack.Screen
name="Main"
options={() => {
return {
headerLeft: (navigation) => <Button title="LEFT BUTTON" onPress={() => {
navigation.toggleDrawer(); // <--- this line throws an error
}} />
}
}}
component={DrawerNavigator} />
https://github.com/react-navigation/react-navigation/issues/55
I have a tab bar with 4 tabs. Each of them have a stack navigator. I want to pop to Top once the tab is switched? I have an inkling it has to do with defaultNavigationOptions. Please suggest me something.
I used this:
import {StackActions} from 'react-navigation'
defaultNavigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation, defaultHandler }) => {
const { routeName } = navigation.state
navigation.dispatch(StackActions.popToTop());
defaultHandler()
},
})
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen
name="Settings"
component={SettingsStackScreen}
listeners={({ navigation, route }) => ({
tabPress: e => {
// navigation.popToTop();
navigation.navigate(route.name);
},
})}
/>
</Tab.Navigator>
</NavigationContainer>
);
}