Hi I am creating an app with react native and I am using react navigation for the menu but I find a problem and now when I create a menu with bottom tabs a header is also created and it gives me a problem for that reason I would like to know how I can solve it this or disappear the header
enter image description here
mi code is
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';
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>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
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>
);
}
I would try adding an option to one of your screens to hide the header. Either the Tab.Screen(s) or one of the Stack's Screen(s) ─ it's up to you based on your use case.
For example:
...
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} options={{headerShown: false}} />
<Tab.Screen name="Settings" component={SettingsStackScreen} options={{headerShown: false}} />
</Tab.Navigator>
</NavigationContainer>
);
}
This way you don't have two nested headers appearing at the same time.
React Navigation even recommends this from their docs when nesting navigators.
When nesting multiple stack, drawer or bottom tab navigator, headers from both child and parent navigators would be shown. However, usually it's more desirable to show the header in the child navigator and hide the header in the screen of the parent navigator.
To achieve this, you can hide the header in the screen containing the navigator using the headerShown: false option.
Reference: https://reactnavigation.org/docs/nesting-navigators/#nesting-multiple-navigators
Related
I am trying to build a react native app but have navigation issues. When the user navigates between screens using gestures, I believe KeyboardAvoidingView creates empty space on the screen. In the following example. When the user swipes back from FormMainScreen to HomeScreen while the keyboard is active, an empty space appears on the Homepage. Please see the screenshots. appretiate any help in advance
App.jsx
import React from "react";
import { KeyboardAvoidingView, Platform } from "react-native";
import { Provider } from "react-redux";
import { store } from "./store";
import { NavigationContainer } from "#react-navigation/native";
import AuthNavigator from "./navigation/AuthNavigator";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : "height"}
// keyboardVerticalOffset={Platform.OS === "ios" ? -64 : 0}
>
{/* NAVIGATION */}
<AuthNavigator />
</KeyboardAvoidingView>
</NavigationContainer>
</Provider>
);
}
AuthNavigator
const AuthNavigator = () => {
return (
<Stack.Navigator
screenOptions={{
headerShown: false
}}
initialRouteName="Home"
>
{/* <Stack.Screen name="Welcome" component={WelcomeScreen} /> */}
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
<Stack.Screen name="Home" component={TabNavigator} />
<Stack.Screen name="FormMain" component={FormMain} />
<Stack.Screen
name="TaskConfirmation"
component={TaskConfirmationScreen}
/>
<Stack.Screen name="ProFound" component={ProFoundScreen} />
</Stack.Navigator>
);
};
HomeScreen in AuthNavigator
return (
<Screen style={tw`bg-white h-full`}>
<View>
<View style={tw`px-2 py-1`}>
<Image
style={{
width: 200,
height: 100,
resizeMode: "contain"
}}
source={logo}
/>
<AppAutocomplete
suggestions={autoCompleteSuggestions}
onSuggestionPress={onSuggestionPress}
onTextChange={handleTextChange}
placeholder="What can we help with"
inputValue={inputValue}
/>
</View>
</View>
</Screen>
);
};
FormMainScreen in AuthNavigator
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<Screen style={{ flex: 1 }}>
<ScrollView style={tw`p-2`} keyboardShouldPersistTaps="handled">
<Text style={tw`text-center text-xl`}>More Info</Text>
{isError && (
<AppText style={tw`text-red-500 py-1`}>{errorMessage}</AppText>
)}
<View>
<View>
<AppText>Street</AppText>
<GooglePlacesAutocomplete
placeholder="1234 N Main St"
styles={toInputBoxStyles}
enablePoweredByContainer={false}
query={{
key: GOOGLE_MAP_APIKEY,
language: "en",
components: "country:us" // Limit results to USA
}}
fetchDetails={true}
returnKeyType={"search"}
nearbyPlacesAPI="GooglePlacesSearch"
debounce={400}
onPress={handleGoogleAutocomplete}
restrictions={{ country: "us" }}
/>
</View>
<AppText>Apt/Unit (optional)</AppText>
<AppInput
placeholder="Apt 2"
value={unitNumber}
onChangeText={setUnitNumber}
keyboardType="numeric"
/>
<AppText>Task</AppText>
<AppInput
placeholder="Task"
value={currentTask.name}
editable={false}
/>
<AppText>Task</AppText>
<AppInput
placeholder="Task"
value={currentTask.name}
editable={false}
/>
<AppText>Task</AppText>
<AppInput
placeholder="Task"
value={currentTask.name}
editable={false}
/>
<AppText>Task</AppText>
<AppInput
placeholder="Task"
value={currentTask.name}
editable={false}
/>
<AppText>Task</AppText>
<AppInput placeholder="Task" value={currentTask.name} />
<AppText>Task</AppText>
<AppInput placeholder="Task" value={currentTask.name} />
<AppText>Service Type</AppText>
<AppInput value={currentTask.service.name} editable={false} />
<AppButton text="Next" onPress={() => handleSubmit()} />
</View>
</ScrollView>
</Screen>
</TouchableWithoutFeedback>
HomePage
FormMain
Swiping back to Home from FormMain
I was setting up the navigations in my App.Js while encountered this error and I am completely clueless that how to solve this issue. Can someone help me?
And just pasting the code of App.Js
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Home from "../screens/Home";
import Login from "../screens/Login";
import Registeration from "../screens/Registeration";
function HomeScreen({ navigation }) {
return (
<View >
<Home />
<Button
title="Go to Login"
onPress={() => navigation.navigate('Login')}
/>
</View>
);
}
function RegisterationScreen({ navigation }) {
return (
<View >
<Registeration />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function LoginScreen({ navigation }) {
return (
<View >
<Login />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Home' }}
/>
<Stack.Screen
name="Registeration"
component={RegisterationScreen}
options={{ title: 'Registeration' }}
/>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ title: 'Login' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
I want to navigate to Home Details which is in HomeStack , from About component which is in AboutStack :
HomeStack.js
export default function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen component={Home} name="Home" />
<Stack.Screen component={HomeDetail} name="HomeDetail" />
</Stack.Navigator>
);
}
AboutStack.js
export default function AboutStack() {
return (
<Stack.Navigator>
<Stack.Screen component={About} name="About" />
<Stack.Screen component={AboutDetail} name="AboutDetail" />
</Stack.Navigator>
);
}
In About component I navigate to the HomeDetails screen which is in HomeStack navigator :
About.js
<Button
title="Go Home details"
onPress={() => navigation.navigate('HomeStack', { screen: 'HomeDetail' })} />
And in HomeDetail screen I try to go back which should go back to the About screen in AboutStack but it goes to Home screen in HomeStack:
HomeDetail.js
<Button onPress={() => navigation.goBack()} title="Go back" />
It goes back to the root screen of it's own Stack .
This is the navigation version I'm using:
"#react-navigation/native": "^5.8.10",
"#react-navigation/stack": "^5.12.8",
How can I go back to About screen in About Stack from HomeDetails screen in HomeStack ?
I solved the problem by passing url params to HomeDetail screen like this :
About.js
navigation.navigate('HomeDetail', { url: 'About' })
HomeDetail.js
function HomeDetail({ navigation, route }) {
console.log(route);
return (
<View style={{ marginTop: 300 }}>
<Text>Home Detail</Text>
<Button onPress={() => navigation.navigate(route.params.url)} title="Go back" />
</View>
);
}
Hello Everyone i have the exact same problem with this one. but the question has no answer yet
im stuck with this all day there is no answer to found i am using the latest react native and latest react navigation package
React navigation focus on input blurs immediately
so this is my form page where at the first load blurs text input when i click the text box
import React, { Component } from 'react'
import { View, Dimensions } from 'react-native'
import {
Container,
Content,
Button,
Text,
Form,
Item,
Input,
Label,
Textarea
} from 'native-base';
import Ion from 'react-native-vector-icons/Ionicons'
class Compose extends Component{
render(){
return(
<Container>
<Content>
<Form style={{ padding: 10 }}>
<Item inlineLabel style={{ marginBottom: 15 }}>
<Ion name="ios-person" size={25} style={{ marginRight: 12 }}/>
<Label>Product Name*</Label>
<Input
/>
</Item>
<Item inlineLabel style={{ marginBottom: 15 }}>
<Ion name="md-pricetags" size={25} style={{ marginRight: 12 }}/>
<Label>Price*</Label>
<Input
/>
</Item>
<Item inlineLabel style={{ marginBottom: 15 }}>
<Ion name="md-arrow-down" size={25} style={{ marginRight: 12 }}/>
<Label>Drop rate*</Label>
<Input
/>
</Item>
<Item inlineLabel style={{ marginBottom: 15 }}>
<Ion name="md-phone-portrait" size={25} style={{ marginRight: 12 }}/>
<Label>Contact number*</Label>
<Input
/>
</Item>
<Textarea
rowSpan={5} bordered
placeholder="Description"
style={{ marginBottom: 15 }}
/>
<Button block success style={{ height: 60, marginBottom: 14 }}>
<Ion name="md-images" size={25} style={{ color: 'white' }}/>
<Text style={{ fontSize: 20 }}>Upload Photos</Text>
</Button>
<Button block danger>
<Ion name="ios-cellular" size={25} style={{ color: 'white' }}/>
<Text>Broadcast</Text>
</Button>
</Form>
</Content>
</Container>
)
}
}
export default Compose
and here is my navigation component
import React, { Component } from 'react';
import { Text } from 'react-native'
//Navigation
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator, TransitionPresets } from '#react-navigation/stack';
//Screens
import { Welcome, Compose } from './src/index'
import {
Header,
Left,
Button,
Icon,
Body,
Title,
Right
}
from 'native-base'
const Stack = createStackNavigator();
const AppbarList = {
welcome: function(navigation){
return null
},
compose: function(navigation){
return (
<Header>
<Left>
<Button transparent rounded>
<Icon name='arrow-back' onPress={()=>{ navigation.goBack() }}/>
</Button>
</Left>
<Body>
<Title></Title>
</Body>
<Right />
</Header>
)
}
}
const Appbar = ( scene, navigation )=> {
const { options } = scene.descriptor;
const title = scene.route.name;
return AppbarList[title.toLowerCase()](navigation)
}
class App extends Component{
render(){
return(
<NavigationContainer>
<Stack.Navigator
headerMode="screen"
screenOptions={{
header: ({ navigation, scene, previous }) => Appbar( scene, navigation )
}}
>
<Stack.Screen
name="Welcome" component={Welcome}
options={{
...TransitionPresets.FadeFromBottomAndroid,
}}
/>
<Stack.Screen
name="Compose" component={Compose}
options={{
...TransitionPresets.FadeFromBottomAndroid,
}}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
}
export default App;
I faced the same problem. Try to disable gestures for Android.
export default () => {
const isAndroidPlatform = isAndroid();
return {
mode: 'modal',
headerMode: 'none',
defaultNavigationOptions: {
gestureEnabled: !isAndroidPlatform,
cardOverlayEnabled: true,
...(
isAndroidPlatform
? TransitionPresets.FadeFromBottomAndroid
: TransitionPresets.ModalPresentationIOS
),
},
};
};
I am using React-Native-Paper's Menu Component
I am trying to show Menu item from the header after tapping an icon.
So far I have managed to show list of item on the screen only.
However, I want to show the menu list from the header.
Due to React Navigation's update from version:4.x to version:5.x, I am a bit confused on how to work this out. I tried following the example here but still I need some time to fully understand hook and the way it works.
All kinds of help would be appreciated.
Workable/Testable code link, code snippets and screenshots provided below:
Snack Link
Register.js:
import { TextInput, Button, Menu, Divider, Provider } from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
class Register extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
}
}
//[ TEST DROP DOWN MENU ]
_openMenu = () => this.setState({ visible: true });
_closeMenu = () => this.setState({ visible: false });
renderMenuExample() {
return (
<View
style={{
paddingTop: 50,
flexDirection: 'row',
justifyContent: 'center'
}}>
<Menu
visible={this.state.visible}
onDismiss={this._closeMenu}
anchor={
< TouchableOpacity
onPress={this._openMenu}
style={{ marginHorizontal: 20 }}
>
<MaterialCommunityIcons name="earth" size={30} style={{ color: 'black' }} />
</TouchableOpacity>
}
>
<Menu.Item onPress={() => { }} title="Item 1" />
<Menu.Item onPress={() => { }} title="Item 2" />
<Divider />
<Menu.Item onPress={() => { }} title="Item 3" />
</Menu>
</View>
);
}
//[ TEST DROP DOWN MENU ]
render() {
return (
<Provider>
{this.renderMenuExample()}
</Provider>
);
}
}
export default Register;
App.js:
import { TextInput, Button, Menu, Divider, Provider } from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import AntDesign from 'react-native-vector-icons/AntDesign';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Register"
component={Register}
options={{
headerBackImage: () => (
<AntDesign name="close" size={30} style={{ color: 'white' }} />
),
headerTitle: () => (
<View>
<Text style={{ flex: 1, fontSize: 20, fontWeight: 'bold', alignSelf: 'center', color: 'white' }}>
Register
</Text>
</View>
),
headerRight: () => (
<TouchableOpacity
onPress={() => {/* I WANT TO SHOW THE MENU HERE */ }}
style={{ marginHorizontal: 20 }}
>
<MaterialCommunityIcons name="earth" size={30} style={{ color: 'white' }} />
</TouchableOpacity>
),
headerStyle: {
backgroundColor: '#2e46ff',
},
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Screenshot:
One possible solution would be to wrap the navigation container with a provider and have a separate component for the menu.
Tried this with your snack and it works
The code would be as below.
const CustomMenu = () => {
const [showMenu, setShowMenu] = React.useState(false);
return (
<View style={{}}>
<Menu
visible={showMenu}
onDismiss={() => setShowMenu(false)}
anchor={
<TouchableOpacity onPress={() => setShowMenu(true)}>
<MaterialCommunityIcons
name="earth"
size={30}
style={{ color: 'black' }}
/>
</TouchableOpacity>
}>
<Menu.Item onPress={() => {}} title="Item 1" />
<Menu.Item onPress={() => {}} title="Item 2" />
<Divider />
<Menu.Item onPress={() => {}} title="Item 3" />
</Menu>
</View>
);
};
function App() {
return (
<Provider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Register"
component={Register}
options={{
headerBackImage: () => (
<AntDesign name="close" size={30} style={{ color: 'white' }} />
),
headerTitle: () => (
<View>
<Text
style={{
flex: 1,
fontSize: 20,
fontWeight: 'bold',
alignSelf: 'center',
color: 'white',
}}>
Register
</Text>
</View>
),
headerRight: () => <CustomMenu />,
headerStyle: {
backgroundColor: '#2e46ff',
},
}}
/>
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}