I want to remove the button back, but leave the header.
My component is as follows. I want to leave the title, and I don’t need the back button.
import React from 'react';
import { View } from 'react-native';
export const TrucksScreen = () => {
return (
<View>
....
</View>
);
});
TrucksScreen.navigationOptions = {
headerTitle: 'Trucks Screen',
};
How can I remove the button back?
Using headerLeft: null will be deprecated in future versions.
Instead use a function like so :
TrucksScreen.navigationOptions = {
headerTitle: 'Trucks Screen',
headerLeft: () => {
return null;
},
};
Cheers !
set headerLeft: null in the navigation Options. and this will remove the back button from the head as I did in the last line of code.
import React from 'react';
import { View } from 'react-native';
export const TrucksScreen = () => {
return (
<View>
....
</View>
);
});
TrucksScreen.navigationOptions = {
headerTitle: 'Trucks Screen',
headerLeft: null,
};
I hope it will help. Ask for doubts
According to the docs you can replace the header back button with whatever you want by passing options param in stack navigator . Do find the working example : expo-snack:
import * as React from 'react';
import { View, Text, Button, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('#expo/snack-static/react-native-logo.png')}
/>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
headerTitle: props => <LogoTitle {...props} />,
headerRight: () => (
<Button
onPress={() => alert('This is a button!')}
title="Info"
color="#00cc00"
/>
),
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Hopeit helps. feel free for doubts
import React from 'react';
import { View, TouchableOpacity, Image, Text } from 'react-native';
import PropTypes from 'prop-types';
import style from '../../../utils/style';
import images from '../../../images/images';
class Header extends React.Component {
constructor(props) {
super(props);
}
onRightIconPress = () => {
if (this.props.onRightIconPress) {
this.props.onRightIconPress();
}
};
render() {
const { title, navigation, showBackIcon, showRightIcon, rightIcon } = this.props;
return (
<View style={style.headerrowcontainer}>
{/* Back Button*/}
{showBackIcon ? (
<TouchableOpacity onPress={() => navigation.goBack()}>
<Image resizeMode="contain" source={images.iconback} style={style.backimage} />
</TouchableOpacity>
) : (
<View />
)}
{/* Title */}
<Text style={style.titleheader}>{title}</Text>
{/* Right Icon */}
{showRightIcon ? (
<Image name={rightIcon} style={style.rightIcon} onPress={this.onRightIconPress} />
) : (
<View />
)}
</View>
);
}
}
Header.defaultProps = {
title: '',
};
Header.propTypes = {
title: PropTypes.string,
};
export default Header;
Home: {
screen: HomeScreen,
navigationOptions: {
headerLeft: null,
}
}
try setting headerLeft: null
Doesn't work in RN6.
TrucksScreen.navigationOptions = {
headerTitle: 'Trucks Screen',
headerLeft: () => {
return null;
},
};
Related
So I'm following along with this tutorial trying to make an app with react native and it uses v3 of react-navigation but I'm trying to use v5. The issue is with this the styling that was previously working in the old version no longer does.
**// setup of navigator**
const Stack = createStackNavigator();
const Travel = () => {
return (
<Stack.Navigator initialRouteName="List">
<Stack.Screen name="Article" component={Article} />
<Stack.Screen
name="List"
component={List}
options={{
title: null,
}}
/>
</Stack.Navigator>
);
};
**// screen in question - List**
const styles = StyleSheet.create({
flex: {
flex: 1,
},
row: {
flexDirection: 'row',
},
header: {
backgroundColor: 'orange',
},
});
export default class List extends React.Component {
static navigationOptions = {
header: (
<View style={[styles.flex, styles.row, styles.header]}> **// styles won't get applied for some reason**
<View>
<Text>Search for a place</Text>
<Text>Destination</Text>
</View>
<View>
<Text>Avatars</Text>
</View>
</View>
),
};
render() {
return <Text>List</Text>;
}
}
I'm at a loss to make this work and look like this: goal navigation
Any idea how to update this code from this v3 version in the tutorial to the v5 support version of react-navigation?
UPDATE:
I've gotten closer to the goal with this code:
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import { Text, View } from 'react-native';
import Article from '../screens/Article';
import { List } from '../screens/List';
const Stack = createStackNavigator();
const ListHead = () => {
return (
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'orange',
}}
>
<View>
<Text>Search for a place</Text>
<Text>Destination</Text>
</View>
<View>
<Text>Avatars</Text>
</View>
</View>
);
};
const Travel = () => {
return (
<Stack.Navigator initialRouteName="List">
<Stack.Screen name="Article" component={Article} />
<Stack.Screen
name="List"
component={List}
options={{
headerTitle: () => <ListHead />,
}}
/>
</Stack.Navigator>
);
};
export default Travel;
However I can't get these to properly be spaced apart like the goal photo and they don't take up the full width.
In react-navigation v5 you can use headerLeft and headerRight for a custom navigation header like this. You can also specify the styling according to your needs.
Here is the code example
export default class List extends React.Component {
static navigationOptions = {
headerLeft: () => (
<View>
<Text>Search for a place</Text>
<Text>Destination</Text>
</View>
),
headerRight: () => (
<View>
<Text>Avatars</Text>
</View>
),
// you can specify your styles here also
headerStyle: {},
headerRightContainerStyle: {},
headerLeftContainerStyle: {},
};
render() {
return <Text>List</Text>;
}
}
I hope this will help you out.!
I can't seem to get any route params in my nested navigator. The params are present in the parent navigator, but they are not reachable in the child navigator.
So the child navigator does render the correct screen, but it does not have any params in the route (namely a category or product id).
It feels like I am misusing some syntax, but I can't quite figure out which one. Here is the stack of code, edited down a bit to make it easier to read.
Snack on Expo
Thank you.
Note: These are separate files so the includes are off.
import * as React from 'react';
import { Text, View, StyleSheet, SafeAreaView } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { NavigationContainer } from '#react-navigation/native'
import { createDrawerNavigator, DrawerContentScrollView, DrawerItem } from '#react-navigation/drawer'
import { createStackNavigator } from '#react-navigation/stack'
import { AppearanceProvider } from 'react-native-appearance'
const Drawer = createDrawerNavigator()
const Stack = createStackNavigator()
const HomeScreen = ({ navigation, route }) => {
return(
<View style={styles.container}>
<Text>Home Screen </Text>
</View>
)
}
const CategoryScreen = ({ navigation, route }) => {
return(
<View>
<Text>Category Screen </Text>
<Text>{JSON.stringify(route)}</Text>
</View>
)
}
const ProductScreen = ({ navigation, route }) => {
return(
<View>
<Text>Product Screen </Text>
<Text>{JSON.stringify(route)}</Text>
</View>
)
}
const CustomDrawerContent = ({ props }) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
<DrawerItem
label="Category 1"
onPress={() =>
props.navigation.navigate('Main', {
Screen: 'Category',
params: { id: 1 },
})
}
/>
<DrawerItem
label="Category 2"
onPress={() =>
props.navigation.navigate('Main', {
Screen: 'Category',
params: { id: 101 },
})
}
/>
</DrawerContentScrollView>
)
}
const MainNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Category" component={CategoryScreen} />
<Stack.Screen name="Product" component={ProductScreen} />
</Stack.Navigator>
)
}
const ApplicationNavigator = () => {
return (
<NavigationContainer initialRouteName="Home">
<Drawer.Navigator
drawerContent={(props) => {
return <CustomDrawerContent props={props} />
}}
>
<Drawer.Screen
name="Home"
component={HomeScreen}
/>
<Drawer.Screen
name="Main"
component={MainNavigator}
/>
</Drawer.Navigator>
</NavigationContainer>
)
}
export default function App() {
return <ApplicationNavigator />
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
padding: 8,
backgroundColor: '#FFFFFF',
},
});
UPDATE
I have noted that if I initialize the params (blank, with values, whichever) outside of the custom drawer content first, the above code begins to work as expected.
Very simple and silly fix that a rubber duck could solve.
Screen !== screen. I was passing in an unknown param to navigate.
I am having a bit of trouble with react-navigation
import React, {useState,useEffect} from 'react';
import {Image} from "react-native";
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Home from "./src/screens/Home.js";
import InvitePage from './src/screens/InvitePage.js';
import WelcomePage from './src/screens/WelcomePage.js';
import NamePage from './src/screens/NamePage.js';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Stack = createStackNavigator();
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require("./assets/Appicon.png")}
/>
);
}
function App() {
const [userName,setuserName]=useState(null);
const [loading, setLoading] = useState(true)
useEffect(() => {
async function getName(){
try {
const result= await AsyncStorage.getItem('namekey')
setuserName(result);
setLoading(false);
}
catch(e) {
setLoading(false);
}
}
getName();
}, []);
if (loading) {
return (
<></>
)
}
return (
<NavigationContainer>
<Stack.Navigator>
{userName ?
(<Stack.Screen name="Home" component={Home}
options={{
headerTitle: props => <LogoTitle {...props} /> ,
headerStyle: {
height: 120,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}/>):(
<>
<Stack.Screen name="WelcomePage" component={WelcomePage}
options={{
title: 'Welcome',
headerStyle: {backgroundColor:'#fff',height: 100 },
}}
/>
<Stack.Screen name="NamePage" component={NamePage}
options={{
title: 'Welcome',
headerStyle: {backgroundColor:'#fff',height: 100 },
}}
/>
</>
)}
<Stack.Screen name="InvitePage" component={InvitePage}
options={{
title: 'Invite',
headerStyle: {backgroundColor:'#fff',height: 100 },
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
This is my app.js.Here, I am reading a file using async storage and then i decide based on that which screen i want to navigate to but the problem is when i go to my name setup page and after saving the name to async storage I can't navigate to home page for some reason
i am getting this error:
The action 'NAVIGATE' with payload {"name":"Home"} was not handled by any navigator.
Do you have a screen named 'Home'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
i think maybe home page is not getting initialized in this code?
This is my namePage:
async function next(){
try {
await AsyncStorage.setItem('namekey', name)
console.log("done")
} catch (e) {
console.log("errorNamePage")
}
navigation.navigate("Home");
}
return(
<View style={styles.headerview}>
<Text style={{fontSize:30,marginTop:250,fontFamily:"AzoSans-Medium",marginLeft:30,marginRight:30}}>Please enter your name</Text>
<TextInput
style={styles.input}
placeholder="Name"
onChangeText={name => setName(name)}
defaultValue={name}
onSubmitEditing={()=>next()}
autoCorrect = {false}
/>
<TouchableOpacity style={{marginTop: 150}} onPress={()=> next()}>
<Image source={require('../../assets/welcome-next.png')} style={{width:100, height: 100,marginLeft:150}} />
</TouchableOpacity>
</View>
);
};
The condition you used in navigator probably separates NamePage and Home, so they are not accessible for each other I guess. Once you get to Name page, userName must be a truthy value to navigate to Home
If you tell about your intention more, people here can show you a simpler solution.
How to add submenu or tabs in the upper part in connection with the lower button and show the name of the lower button in the header of the application.
import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer } from 'react-navigation';
import { MaterialIcons, MaterialCommunityIcons } from '#expo/vector-icons';
import Splash from '../screens/Splash';
import NewsListScreen from '../screens/NewsListScreen';
import NewsItemScreen from '../screens/NewsItemScreen';
const StackNavigator = createStackNavigator({
//Splash: {screen: Splash},
News: {
screen: NewsListScreen
},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
}
});
const BottomTabNavigator = createBottomTabNavigator({
Home: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialIcons name="home" size={24} />
}
},
News: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialCommunityIcons name="newspaper-variant-outline" size={24} />
}
}
})
export default createAppContainer(BottomTabNavigator);
What I want to achieve is the following:
As you can see, the bottom button [News] has three referential buttons in the upper part [FEATURED], [RELEVANT], [SEARCH] and, in addition to that, it recovers the name of the bottom button and adds it to the application header below the top buttons.
[EDITED]
Your NewsListScreen screen, instead of just being a tab bar component, can be something like that:
function NewsListScreen = (props) => (
<View>
<Text>News</Text>
<TabBarComponent {...props} />
</View>
)
function TabBarComponent = createMaterialTopTabNavigator({
featured: ... ,
relevant: ... ,
search: ... ,
})
That being said, if you can, you should update your project to react navigation v5, which is I think much more user friendly.
Final Output:
Implementation using react-navigation v5 :
import * as React from 'react';
import { Text, View, StyleSheet, Dimensions } from 'react-native';
import Constants from 'expo-constants';
import {
NavigationContainer,
useNavigationState,
} from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
const TopTab = createMaterialTopTabNavigator();
const BottomTab = createBottomTabNavigator();
/*
Here I am using MaterialTopTabNavigator instead of StackNavigator,
which is a better choice based on UI snapshot in this case.
*/
function NewsTopTabs() {
/*
in case you want to set the title dynamically then you can use the
useNavigationState hook but as there are just two bottom tabs so
I am using hardcoded values.
*/
const nav = useNavigationState((state) => state);
return (
<>
<View style={styles.titleBar}>
<Text style={styles.title}>News</Text>
</View>
<TopTab.Navigator>
<TopTab.Screen name="Featured" component={Featured} />
<TopTab.Screen name="Relevant" component={Relevant} />
<TopTab.Screen name="Search" component={Search} />
</TopTab.Navigator>
</>
);
}
function MatchesTopTabs() {
return (
<>
<View style={styles.titleBar}>
<Text style={styles.title}>Matches</Text>
</View>
<TopTab.Navigator>
<TopTab.Screen name="Featured" component={Featured} />
<TopTab.Screen name="Relevant" component={Relevant} />
<TopTab.Screen name="Search" component={Search} />
</TopTab.Navigator>
</>
);
}
function MyBottomTabs({ navigation }) {
return (
<BottomTab.Navigator>
<BottomTab.Screen name="News" component={NewsTopTabs} />
<BottomTab.Screen name="Matches" component={MatchesTopTabs} />
</BottomTab.Navigator>
);
}
//[FEATURED], [RELEVANT], [SEARCH]
export default function App() {
return (
<NavigationContainer>
<MyBottomTabs />
</NavigationContainer>
);
}
//[FEATURED], [RELEVANT], [SEARCH]
const Featured = () => {
const nav = useNavigationState((state) => state);
return (
<View style={styles.screen}>
<Text>Featured</Text>
</View>
);
};
const Relevant = () => {
const nav = useNavigationState((state) => state);
return (
<View style={styles.screen}>
<Text>Relevant</Text>
</View>
);
};
const Search = () => {
const nav = useNavigationState((state) => state);
return (
<View style={styles.screen}>
<Text>Search</Text>
</View>
);
};
const styles = StyleSheet.create({
titleBar: {
height: 50,
width: Math.round(Dimensions.get('window').width),
backgroundColor: 'white',
justifyContent: 'center',
borderBottomColor: "lightgrey",
borderBottomWidth: 1,
paddingLeft: 10,
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
screen:{
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
Working Example: Expo Snack
I trying to render StackNavigator inside TabNavigator. The Tabs are working fine, but i cannot link the button
In simple words, there's a button inside the "Feed" section of the TabNavigator "Tabs" . When clicked on the button, it should go to "UserDetails.js" via StackNavigator.
Please help!
Here is my index.android.js
export default class HackernoonNavigation extends Component {
render() {
return (
<Tabs />
);
}
}
export const Tabs = TabNavigator({
Feed: {
screen: Feed,
},
Me: {
screen: Me,
},
});
And here is the file "Feed.js" , inside which there is a button that leads to "UserDetail.js"
export default class Feed extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Feed!
</Text>
<Button
onPress={() => this.props.navigation.navigate('Details')}
title="User Details"
/>
</View>
);
}
}
export const FeedStack = StackNavigator({
Details: { screen: UserDetail },
});
You can do it by defining tabnavigator inside stacknavigator as screen like in this way -
const StackNaviApp = StackNavigator({
UserDetails: { screen: UserDetails},
Feed: {
screen: TabNavigator({
Feed: { screen: Feed},
Me: { screen: Me}
}, {
tabBarOptions: {
showIcon: true,
lazy: true,
activeTintColor: '#7567B1',
labelStyle: {
fontSize: 16,
fontWeight: '600'
}
}
})
}});
export default StackNaviApp;
Taking Feed & Me inside TabNavigator & UserDetails inside StackNavigator directly . For more detail you can refer the source code from here -
http://androidseekho.com/others/reactnative/switching-between-stack-navigator-to-tab-navigator/
So I have a ListView on a Tab Screen and when I click on the List Item its navigating to a component called QR Code. So when I click a List Item the camera will be opened in a new window with StackNavigator.... I show you my code down below. Maybe it helps you to find your fault.
import React, {
Component,
} from 'react';
import {
// AppRegistry,
// Dimensions,
ListView,
StyleSheet,
Text,
TouchableOpacity,
TouchableHighlight,
View,
AsyncStorage
} from 'react-native';
import { SwipeListView, SwipeRow } from 'react-native-swipe-list-view';
import moment from 'moment';
import{createStackNavigator} from 'react-navigation';
import { Icon } from 'react-native-elements'
import QrCode from '../components/QrCode';
class SwipeList extends Component {
static navigationOptions = {
title: 'Scanner auswählen',
headerTintColor: 'white',
headerStyle: {backgroundColor: '#444444'},
headerTitleStyle: { color: 'white' },
};
constructor(props) {
super(props);
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
scannerAvailable:false,
listType: 'FlatList',
listViewData: this.ds,
}
...
goToQrCodeScreen=(scanner)=>{
this.props.navigation.navigate('QrCode',{
scannerName: scanner.scannerName,
scannerValidityEnd: scanner.scannerValidityEnd,
scannerId: scanner.scannerId,
dataMacroId: scanner.dataMacroId,
hash:scanner.hash,
requestKey: scanner.requestKey,
})
}
...
render() {
return (
<View style={styles.container}>
<View>
<SwipeListView
dataSource={this.state.listViewData}
renderRow={ data => (
<View >
<TouchableHighlight
onPress={()=>this.goToQrCodeScreen(data)}
style={styles.rowFront}
underlayColor={'#AAA'}>
<Text> <Text style={[styles.listItemName,styles.textBold] } >{data.scannerName} </Text>
<Text style={styles.listItemValid}> gültig bis {moment(data.scannerValidityEnd).format('DD.MM.YYYY')}</Text>
</Text>
</TouchableHighlight>
</View>
)}
renderHiddenRow={ (data, secId, rowId, rowMap) => (
<View style={styles.rowBack}>
<TouchableOpacity style={[styles.backRightBtn, styles.backRightBtnRight]} onPress={ _ => this.deleteRow(data.scannerId,rowMap, `${secId}${rowId}`) }>
<Icon
name='trash'
type='font-awesome'
color='white'/>
<Text style={styles.backTextWhite}>
Löschen</Text>
</TouchableOpacity>
</View>
)}
rightOpenValue={-100}
enableEmptySections={true}
/>
</View>
</View>
);
}
}
const StackNavigation = createStackNavigator(
{
SwipeList:SwipeList ,
QrCode:QrCode
},
{
initialRouteName: 'SwipeList',
}
);
export default StackNavigation;
I deleted the code you dont need. I call the method goToQrCodeScreen() to navigate.
My fault was that I dont exported the StackNavigator. Now its working.
you need to wrap your feed in another component :
const FeedStack = createStackNavigator();
function FeedWrapper() {
return (
<HomeStack.Navigator>
<FeedStack .Screen name="Feed" component={Feed} />
<FeedStack .Screen name="Details" component={Details} />
</HomeStack.Navigator>
);
}
see https://reactnavigation.org/docs/tab-based-navigation