What is the proper way to have only one header with Open Drawer and Back button? - react-native

What I need is a single header with a back button on StackScreen2 and a toggle drawer button in StackScreen1.
I apologise for my poor writing and English.
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function StackScreen1({ navigation }) {
return (
<View>
<Text>StackScreen1</Text>
<Button title="Go To StackScreen2" onPress={() => navigation.navigate("StackScreen2")} />
</View>
)
}
function StackScreen2() {
return (
<View>
<Text>StackScreen2</Text>
</View>
)
}
function DrawerScreen1() {
return (
<Stack.Navigator>
<Stack.Screen name="StackScreen1" component={StackScreen1} />
<Stack.Screen name="StackScreen2" component={StackScreen2} />
</Stack.Navigator>
)
}
function DrawerScreen2() {
return (
<View>
<Text>DrawerScreen2</Text>
</View>
)
}
const Drawer = createDrawerNavigator();
export default function Test3() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="DrawerScreen1" component={DrawerScreen1} />
<Drawer.Screen name="DrawerScreen2" component={DrawerScreen2} />
</Drawer.Navigator>
</NavigationContainer>
);
}
StackScreen1
StackScreen2
I tried hiding drawer header but then I don't have toggle drawer button anywhere.

Check below code for drawer navigation:
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator useLegacyImplementation initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You can check more about drawer here.

May be this will help you!
import * as React from 'react';
import { Ionicons, FontAwesome } from '#expo/vector-icons';
import { Button, View, Text, Pressable,Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createDrawerNavigator } from '#react-navigation/drawer';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('SettingsScreen')}
/>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.goBack()}
/>
</View>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator
useLegacyImplementation
// screenOptions={{
// drawerLabelStyle: { fontSize: 17, color: '#000',marginLeft:-30 }
// }}
>
<Drawer.Screen
name="HomeScreen"
component={DetailsScreen}
screenOptions={{
headerShown: false,
}}
/>
</Drawer.Navigator>
);
}
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen
name="SettingsScreen"
component={MyDrawer}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Ionicons name="md-home" size={24} color={'#eee'} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
<Tab.Screen
name="DetailsScreen"
component={DetailsScreen}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Image source={{uri:"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUAN0zLcvLFjdaYN1dBRSKoIuJndRW6VuX85w2yzEzxvTwO3B0Y_gv1x8kVDISNKJEbq0&usqp=CAU"}}
style={{width:24,height:24,borderRadius:24}} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
</Tab.Navigator>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>2</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="HomeScreen">
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SettingsScreen"
component={MyTabs}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

Related

Why my panel is hiding the body of my views?

i want to build a built a navigation with BottomTabNavigator but i dont know what happen i never see the body of my screens, something is hidding the body, i created a demo to demostrate you the wrong, but its too simple.
this is the file App.js
import React from 'react'
//import { Provider } from 'react-native-paper'
import { Provider, useSelector } from 'react-redux'
import { createStore } from 'redux'
import { NavigationContainer } from '#react-navigation/native'
import { View, Text } from 'react-native'
import { createStackNavigator } from '#react-navigation/stack'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
const Stack = createStackNavigator()
function HomeScreen() {
return (
<View
style={{
flexDirection: 'row',
height: 100,
padding: 20,
}}
>
<View style={{ backgroundColor: 'blue', flex: 0.3 }} />
<View style={{ backgroundColor: 'red', flex: 0.5 }} />
<Text>Hello World!</Text>
</View>
)
}
function SettingsScreen() {
return (
<View
style={{
backgroundColor: 'red',
flex: 1,
color: 'green',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text>Settings!</Text>
</View>
)
}
const Tab = createBottomTabNavigator()
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="main">
<Stack.Screen name="loginScreen" component={SettingsScreen} />
<Stack.Screen name="main" component={MyTabs} />
</Stack.Navigator>
</NavigationContainer>
)
}
i am trying to do, before to user is logged i would like to hidde the tabs
something is hidding
edit 1: why i have 2 headers?
On the web, #react-navigation/bottom-tabs mistakenly treat screens in the tab as inactive and detaches them.
The solution is to disable detach inactive screens for bottom tab.
import React from "react";
//import { Provider } from 'react-native-paper'
import { Provider, useSelector } from "react-redux";
import { createStore } from "redux";
import { NavigationContainer } from "#react-navigation/native";
import { View, Text } from "react-native";
import { createStackNavigator } from "#react-navigation/stack";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
const Stack = createStackNavigator();
function HomeScreen() {
return (
<View
style={{
flexDirection: "row",
height: 100,
padding: 20,
}}
>
<View style={{ backgroundColor: "blue", flex: 0.3 }} />
<View style={{ backgroundColor: "red", flex: 0.5 }} />
<Text>Hello World!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View
style={{
backgroundColor: "red",
flex: 1,
color: "green",
justifyContent: "center",
alignItems: "center",
}}
>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator detachInactiveScreens={false}>
<Tab.Screen name="Home" component={HomeScreen} options={{headerShown:false}} />
<Tab.Screen name="Settings" component={SettingsScreen} options={{headerShown:false}}/>
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="main" >
<Stack.Screen name="loginScreen" component={SettingsScreen} options={{headerShown:false}}/>
<Stack.Screen name="main" component={MyTabs} options={{headerShown:false}} />
</Stack.Navigator>
</NavigationContainer>
);
}
Moving between screens
You can create a state for handling user logged in status or you can also use redux for it so It will automatically navigate to the main screen after user logged in
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
{state.userToken == null ? (
// No token found, user isn't signed in
<Stack.Screen name="loginScreen" component={LoginScreen} />
) : (
// User is signed in
<Stack.Screen name="main" component={MyTabs} />
)}
</Stack.Navigator>
</NavigationContainer>
);
}
More details Here

React Native Expo app showing two topbars

I'm following this example: https://reactnavigation.org/docs/tab-based-navigation#a-native-stack-navigator-for-each-tab
I've copy pasted the example from the website. However, this is what I see:
I've the following packages in package.json:
"#react-navigation/bottom-tabs": "^6.0.9",
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"#react-navigation/stack": "^6.0.11",
Here's my code:
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import Ionicons from '#expo/vector-icons/Ionicons';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function AnalyticsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Analytics screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="HomeScreen" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="SettingsScreen" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const AnalyticsStack = createNativeStackNavigator();
function AnalyticsStackScreen() {
return (
<AnalyticsStack.Navigator>
<AnalyticsStack.Screen name="Analytics" component={SettingsScreen} />
<AnalyticsStack.Screen name="Details" component={DetailsScreen} />
</AnalyticsStack.Navigator>
)
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = 'home';
} else if (route.name === 'Settings') {
iconName = 'search';
} else if (route.name === 'Analytics') {
iconName = 'bar-chart'
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: 'tomato',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
<Tab.Screen name="Analytics" component={AnalyticsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
You can easily hide navigator headers like this:
<YourNavigator.Navigator
screenOptions={{ headerShown: false /* <-- This will hide your header */ }}
>
<YourNavigator.Screen
name='Settings' /* <-- This name will be shown as header if true */
component={YourSettingsNavigator}
/>
</YourNavigator.Navigator>
Since YourSettingsNavigator is another Navigator, you are nesting navigators in each other. When doing this make sure to set headerShown: false in at least one of the navigators or you get two headers.

React Navigation V6 Bottom Tab Not Displaying

I'm following the guide here from React Navigation V6 and my component is not displaying as it is intended to. When I swap out createBottomTabNavigator with createMaterialTopTabNavigator I get my display. Can somebody help me figure out why the output is behaving this way? Photos are attached below the code. Thank you to anybody that can help!
Edit: React-Native-Web sometimes displays things incorrectly. When viewed on a phone it looks correct.
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function FeedScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed Screen!</Text>
</View>
);
}
function HomeScreen({ navigation }:any) {
return (
<View >
<Text>Home screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function NotificationsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Notifications Screen</Text>
</View>
);
}
function ProfileScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile Screen</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to tabs"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}
function BasicStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: true }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
)
}
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Notifications" component={NotificationsScreen} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<BasicStack/>
</NavigationContainer>
);
}
Output with createBottomTabNavigator
Output with createMaterialTopTabNavigator

ReactNative how to disable click on drawer menu item

the drawer menu setup is like below.
how can i disable click on first Drawer.Screen ?
it must show a single image!!
also how can i hide one element programmatically?
<Drawer.Navigator
initialRouteName="Feed"
drawerPosition="right"
drawerStyle={{
backgroundColor: '#c7c4b8',
width: 240,
}}
overlayColor="transparent">
<Drawer.Screen
name="Profile2"
component={Profile2}
options={{ drawerLabel: '', drawerIcon: ({ focused, size }) => (
<Image source={require('./images/3.jpg')} resizeMode={'cover'} style={{ width: '100%', height: 200 }} />)
}}
/>
<Drawer.Screen
name="Home"
component={Notifications}
options={{ drawerLabel: 'Feed' }}
/>
<Drawer.Screen
name="Routes"
component={Profile}
options={{ drawerLabel: 'Routes' }}
/>
</Drawer.Navigator>
For add header or whatever you want you should use drawerContent prop and there you can make your custom drawer or manipulate the existing one like in the example below.
For show/hide screen in a drawer programatically you can just use it with useState or pass a redux store and conditionally render it or not, remember that navigator its just a react component.
I let you a snack to check it online as well.
https://snack.expo.io/#anthowm/drawer-navigation-%7C-react-navigation
import * as React from 'react';
import {useState} from 'react';
import { View, Text, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
function Feed() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed Screen</Text>
</View>
);
}
function Article() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Article Screen</Text>
</View>
);
}
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<Image source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}} resizeMode={'cover'} style={{ width: '100%', height: 200 }} />
<DrawerItemList {...props} />
<DrawerItem
label="Hide Screen"
onPress={() => props.setShow(false)}
/>
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
const [show, setShow] = useState(true);
return (
<Drawer.Navigator drawerContent={props => <CustomDrawerContent setShow={setShow} {...props} />}>
<Drawer.Screen name="Feed" component={Feed} />
{show && <Drawer.Screen name="Article" component={Article} />}
</Drawer.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyDrawer />
</NavigationContainer>
);
}

How can I access a current navigation inside a React.Component using reactnavigation 5?

I'm now using react-navigation version 5 following an expo tutorial to navigate to another screen inside a Stack (embedded in a Tab Navigator).
In the tutorial, they always used a function to init a specific screen so the navigation parameter will easy to be called inside the function's body.
Eg:
function HomeScreen({ navigation })
//Called
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
But, if I construct a React.Component instead, how can I access the navigation inside that Component to navigate to another component? plz
Please run the codes bellow on expo if my explanations are bad.
Thanks,
import * as React from 'react';
import { Button, Text, View, Alert } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
class Options extends React.Component {
navigaeToAnotherScreen() {
console.log('How can I access current navigation plz?');
}
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Hello, world! Option</Text>
<Button title="Go To Main" onPress={() => this.navigaeToAnotherScreen() }/>
</View>
);
}
}
function OptionsScreen({ navigation }) {
return (
<Options/>
);
}
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
<Button title="Detail" onPress={ () => navigation.push('Options')}/>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.push('Details')}
/>
</View>
);
}
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
<HomeStack.Screen name="Options" component={OptionsScreen} />
</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} />
</Tab.Navigator>
</NavigationContainer>
);
}
try this
I noticed you didn't pass existing props to Options
function OptionsScreen({ navigation }) {
return (
<Options navigation={navigation} />
);
then try this
navigaeToAnotherScreen() {
this.props.navigation.navigate("AnyScreen");
}