Deep Linking in Nested Navigators in react navigation - react-native

I am using react-navigation and as per the structure of my application, we have a tab navigator inside stack navigator, I am not been able to find any proper guide for implementing Deep-Linking.
https://v1.reactnavigation.org/docs/deep-linking.html. this doesn't give any reference for nested navigators.

You have to basically pass a path to every upper route untill you come to you nested route. This is indipendent of the type of navigator you use.
const HomeStack = createStackNavigator({
Article: {
screen: ArticleScreen,
path: 'article',
},
});
const SimpleApp = createAppContainer(createBottomTabNavigator({
Home: {
screen: HomeStack,
path: 'home',
},
}));
const prefix = Platform.OS == 'android' ? 'myapp://myapp/' : 'myapp://';
const MainApp = () => <SimpleApp uriPrefix={prefix} />;
In this case to route to an inner Navigator this is the route: myapp://home/article.
This example is using react-navigation#^3.0.0, but is easy to transfer to v1.

So, after the arrival of V3 of react navigation, things got extremely stable. Now i will present you a navigation structure with deep-linking in a Switch navigator -> drawerNavigator-> tabNavigator -> stack-> navigator. Please go step by step and understand the structure and keep referring to official documentation at everystep
With nested navigators people generally mean navigation structure which consists of drawer navigator, tab navigator and stackNavigator. In V3 we have SwitchNavigator too. So let's just get to the code,
//here we will have the basic React and react native imports which depends on what you want to render
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View, Animated, Easing, Image,
Button,
TouchableOpacity, TextInput, SafeAreaView, FlatList, Vibration, ActivityIndicator, PermissionsAndroid, Linking
} from "react-native";
import { createSwitchNavigator, createAppContainer, createDrawerNavigator, createBottomTabNavigator, createStackNavigator } from "react-navigation";
export default class App extends Component<Props> {
constructor() {
super()
this.state = {
isLoading: true
}
}
render() {
return <AppContainer uriPrefix={prefix} />;
}
}
class WelcomeScreen extends Component {
state = {
fadeAnim: new Animated.Value(0.2), // Initial value for opacity: 0
}
componentDidMount() {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: 1,
easing: Easing.back(), // Animate to opacity: 1 (opaque)
duration: 1000,
useNativeDriver: true // Make it take a while
}
).start(); // Starts the animation
}
render() {
let { fadeAnim } = this.state;
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center", backgroundColor: '#000' }}>
<Animated.View // Special animatable View
style={{ opacity: fadeAnim }}
>
<TouchableOpacity
onPress={() => this.props.navigation.navigate("Dashboard")}
style={{
backgroundColor: "orange",
alignItems: "center",
justifyContent: "center",
height: 30,
width: 100,
borderRadius: 10,
borderColor: "#ccc",
borderWidth: 2,
marginBottom: 10
}}
>
<Text>Login</Text>
</TouchableOpacity>
</Animated.View>
<Animated.View // Special animatable View
style={{ opacity: fadeAnim }}
>
<TouchableOpacity
onPress={() => alert("buttonPressed")}
style={{
backgroundColor: "orange",
alignItems: "center",
justifyContent: "center",
height: 30,
width: 100,
borderRadius: 10,
borderColor: "#ccc",
borderWidth: 2
}}
>
<Text> Sign Up</Text>
</TouchableOpacity>
</Animated.View>
</View>
);
}
}
class Feed extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Button
onPress={() => this.props.navigation.navigate("DetailsScreen")}
title="Go to details"
/>
</View>
);
}
}
class Profile extends Component {
render() {
return (
<SafeAreaView style={{ flex: 1, }}>
//Somecode
</SafeAreaView>
);
}
}
class Settings extends Component {
render() {
return (
<View style={{ flex: 1 }}>
//Some code
</View>
);
}
}
const feedStack = createStackNavigator({
Feed: {
screen: Feed,
path: 'feed',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Feed",
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details",
};
}
}
});
const profileStack = createStackNavigator({
Profile: {
screen: Profile,
path: 'profile',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Profile",
headerMode: 'Float',
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
}
}
});
const settingStack = createStackNavigator({
Settings: {
screen: Settings,
path: 'settings',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Settings",
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
},
}
});
const DashboardTabNavigator = createBottomTabNavigator(
{
feedStack: {
screen: feedStack,
path: 'feedStack',
navigationOptions: ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarLabel: "Feed",
tabBarVisible,
//iconName :`ios-list${focused ? '' : '-outline'}`,
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-list" color={tintColor} size={25} />
)
};
}
},
profileStack: {
screen: profileStack,
path: 'profileStack',
navigationOptions: ({ navigation, focused }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false
}
return {
tabBarVisible,
tabBarLabel: "Profile",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-man" color={tintColor} size={25} />
)
};
// focused:true,
}
},
settingStack: {
screen: settingStack,
path: 'settingsStack',
navigationOptions: ({ navigation }) => {
let tabBarVisible = true;
if (navigation.state.index > 0) {
tabBarVisible = false;
}
return {
tabBarVisible,
tabBarLabel: "Settings",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-options" color={tintColor} size={25} />
)
}
}
},
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
// headerTitle: routeName,
header: null
};
},
tabBarOptions: {
//showLabel: true, // hide labels
activeTintColor: "orange", // active icon color
inactiveTintColor: "#586589" // inactive icon color
//activeBackgroundColor:'#32a1fe',
}
}
);
const DashboardStackNavigator = createStackNavigator(
{
DashboardTabNavigator: {
screen: DashboardTabNavigator,
path: 'dashboardtabs'
},
DetailsScreen: {
screen: Detail,
path: 'details',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details"
};
}
}
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
name="md-menu"
size={30}
onPress={() => navigation.openDrawer()}
/>
)
};
}
}
);
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: DashboardStackNavigator,
path: 'welcome'
},
DetailsScreen: {
screen: Detail,
path: 'friends',
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Details",
};
}
}
});
//Switch navigator , will be first to load
const AppSwitchNavigator = createSwitchNavigator({
Welcome: {
screen: WelcomeScreen,
},
Dashboard: {
screen: AppDrawerNavigator,
path: 'welcome'
}
});
const prefix = 'myapp://';
const AppContainer = createAppContainer(AppSwitchNavigator);
For the process to setup React-navigation deep-linking please follow the official documentation
DetailsScreen was in my different folder and that will have class component of your choice
To launch the App the deep-link URL is myapp://welcome
To go to root page the deep-link URL is myapp://welcome/welcome
(this will reach at first page of first tab of tab navigator)
To go to any particular screen of tab navigator (suppose details
screen in profile tab) -
myapp://welcome/welcome/profileStack/details

const config = {
Tabs: {
screens: {
UserProfile: {
path: 'share//user_share/:userId',
parse: {
userId: (userId) => `${userId}`,
},
},
},
},
};
const linking = {
prefixes: ['recreative://'],
config,
};
if you have a screen in tab navigator you can do it like this via react-navigation v5

Related

React native navigate throwing error 'Can not read property 'navigate' of undefined

I am running a code that displays menu of various dishes where users can press one of the dishes they will be taken to "Dishdetail" screen where read about the dish. The problem is when we get to the point where we click the app is using navigate but the app is throwing some error message that says the "TypeError: Can not read Property 'navigate' of undefined". You can see the code I have it declared in the code below.
MainComponent.js
import React, { Component } from 'react' ;
import Menu from './MenuComponent' ;
import { View, Image, StyleSheet, ScrollView, Text,Platform } from 'react-native'
//import { Platform } from '#unimodules/core';
import Home from './HomeComponent';
import Dishdetail from './DishdetailComponent' ;
import Contact from './ContactComponent' ;
import About from './AboutComponent';
import { Icon } from 'react-native-elements';
import { createStackNavigator, createDrawerNavigator,SafeAreaView,DrawerItems } from 'react-navigation';
//1. ActionCreators import
import { fetchDishes, fetchComments, fetchPromos, fetchLeaders} from '../redux/ActionCreators';
//1.import to connect to redux
import { connect } from 'react-redux';
import {baseUrl } from '../shared/baseUrl';
//2.leaders state from store
const mapStateToProps = state => {
return {
}
}
//2. get the actions creators
const mapDispatchToProps = dispatch => ({
fetchDishes: () => {dispatch(fetchDishes())},
fetchComments:() => {dispatch(fetchComments())},
fetchPromos: () => {dispatch(fetchPromos())},
fetchLeaders: () => {dispatch(fetchLeaders())}
})
//() => <Menu/>
const MenuNavigator = createStackNavigator({
Menu: { screen: () => <Menu/>,
navigationOptions: ({ navigation }) => ({
headerLeft: <Icon name='menu' size={24}
color='white'
onPress={ () => navigation.toggleDrawer()}
/>
})
},
Dishdetail: { screen: () => <Dishdetail/> }
},
{
initialRouteName: 'Menu',
navigationOptions: {
headerStyle: {
backgroundColor: '#512DA8'
},
headerTintColor: '#fff',
headerTitleStyle: {
color: '#fff'
}
}
})
//Create stacknavigator for Home Component
const HomeNavigator = createStackNavigator({
Home: { screen: () => <Home/> }
},
{
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: '#512DA8'
},
headerTintColor: '#fff',
headerTitleStyle: {
color: '#fff'
},
headerLeft: <Icon name='menu' size={24}
color='white'
onPress={() => navigation.toggleDrawer()}
/>
})
});
//Create stacknavigator for Contact Component
const ContactNavigator = createStackNavigator({
Contact: { screen: () => <Contact/>}
},
{
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: '#512DA8'
},
headerTintColor: '#fff',
headerTitleStyle: {
color: '#fff'
},
headerLeft: <Icon name='menu' size={24}
color='white'
onPress={() => navigation.toggleDrawer()}
/>
})
});
//Create stacknavigator for About Component
const AboutNavigator = createStackNavigator({
About: { screen: () => <About />}
},
{
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: '#512DA8'
},
headerTintColor: '#fff',
headerTitleStyle: {
color: '#fff'
},
headerLeft: <Icon name='menu' size={24}
color='white'
onPress={() => navigation.toggleDrawer()}
/>
})
});
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<SafeAreaView style= {StyleSheet.container}
forceInset={{ top: 'always', horizontal: 'never'}} >
<View style={styles.drawerHeader} >
<View style={{flex:1}} >
<Image source={require('./images/logo.png')}
style={styles.drawerImage} />
</View>
<View style={{flex: 2}} >
<Text style={styles.drawerHeaderText} >Ristorante Con Fusion</Text>
</View>
</View>
<DrawerItems {...props } />
</SafeAreaView>
</ScrollView>
)
//Create drawerNavigator for all Components
// Modified
const MainNavigator = createDrawerNavigator({
Home:
{
screen: HomeNavigator,
navigationOptions: {
title: 'Home',
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Icon
name='home'
type='font-awesome'
size={24}
color={tintColor}
/>
)
}
},
About:
{
screen: AboutNavigator,
navigationOptions: {
title: 'About Us',
drawerLabel: 'About Us',
drawerIcon: ({ tintColor }) => (
<Icon
name='info-cirlce'
type='font-awesome'
size={24}
color={tintColor}
/>
)
}
},
Menu:
{
screen: MenuNavigator,
navigationOptions: {
title: 'Menu',
drawerLabel: 'Menu',
drawerIcon: ({ tintColor }) => (
<Icon
name='list'
type='font-awesome'
size={24}
color={tintColor}
/>
)
}
},
Contact:
{
screen: ContactNavigator,
navigationOptions: {
title: 'Contact Us',
drawerLabel: 'Contact Us',
drawerIcon: ({ tintColor }) => (
<Icon
name='address-card'
type='font-awesome'
size={22}
color={tintColor}
/>
)
}
}
},{
drawerBackgroundColor: '#D1C4E9',
contentComponent: CustomDrawerContentComponent
})
class Main extends Component {
//3. Actioncreators to be loaded by componentDidMount()
componentDidMount() {
this.props.fetchDishes();
this.props.fetchComments();
this.props.fetchPromos();
this.props.fetchLeaders();
}
//<Menu />:Display all dishes and when user clicks one of them
//<Dishdetail>: filter the selectedDish and display its detail underneath
render() {
return (
<View style={{flex: 1, paddingTop: Platform.OS === 'ios' ? 0: Expo.Constants.statusBarHeight }}>
<MainNavigator />
</View>
)
}
}
const styles = StyleSheet.create ({
container: {
flex: 1
},
drawerHeader:{
backgroundColor: '#512DA8',
height: 140,
alignItems: 'center',
justifyContent: 'center',
flex: 1,
flexDirection: 'row'
},
drawerHeaderText: {
color: 'white',
fontSize: 24,
fontWeight: 'bold'
},
drawerImage: {
margin: 10,
width: 80,
height: 60
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Main);
MenuComponent.js
import React, { Component } from 'react' ;
import { FlatList } from 'react-native' ;
import { Tile } from 'react-native-elements' ;
//import { DISHES} from '../shared/dishes';
//1.import to connect to redux
import { connect } from 'react-redux';
import { baseUrl } from '../shared/baseUrl';
//2.leaders state from store
const mapStateToProps = state => {
return {
dishes: state.dishes
}
}
//functional component
class Menu extends Component {
constructor(props) {
super(props);
}
//display the Menu navigation at the top
static navigationOptions = {
title : 'Menu'
}
//onPress uses the navigate to pass the dishId to Dishsetail
//to display the dish detail of the selected dish
render() {
//const {navigate} = this.props.navigation ;
const renderMenuItem = ({item, index}) => {
return (
<Tile
key={index}
title={item.name}
caption={item.description}
featured
onPress={() => navigate('Dishdetail', { dishId: item.id })}
imageSrc={{ uri: baseUrl + item.image }}
/>
);
}
//extract the navigation comp passed to be used to pass
//dishId to Dishdetail
//const { navigate } = this.props.navigation ;
return (
<FlatList
data= {this.props.dishes.dishes}
renderItem={renderMenuItem}
keyExtractor={Item => Item.id.toString() }
/>
)
}
}
export default connect(mapStateToProps)(Menu);
DishdetailComponent.js
import React, { Component } from 'react' ;
import { View, Text, ScrollView, FlatList } from 'react-native' ;
import { Card, Icon } from 'react-native-elements' ;
//import { DISHES} from '../shared/dishes';
//import { COMMENTS } from '../shared/comments';
//1.import to connect to redux
import { connect } from 'react-redux';
import {baseUrl } from '../shared/baseUrl';
//2.leaders state from store
const mapStateToProps = state => {
return {
dishes: state.dishes,
comments: state.comments
}
}
//functional component: Display the selectedDish name, image and
//description using <Card> element
function RenderDish(props){
const dish = props.dish;
if (dish != null) {
return (
<Card
featuredTitle={dish.name}
image={{ uri: baseUrl + dish.image }}
>
<Text style={{margin: 10}}>
{dish.description}
</Text>
<Icon
raised
reverse
name={props.favorite ? 'heart' : 'heart-o'}
type='font-awesome'
color='#f50'
onPress={() => props.favorites ? console.log('Already favorite'): props.onPress() }
/>
</Card>
)
}
else {
return (<View></View>)
}
}
// display comments associted with dish
function RenderComments(props) {
// pull the content out from comments array
const comments = props.comments;
const renderCommentsItem = ({ item , index}) => {
return (
<View key={index} style={{ margin: 10}} >
<Text style={{fonSize: 14 }}>{item.comment}</Text>
<Text style={{fontSize: 12}}>{item.rating} Stars</Text>
<Text style={{ fontSize: 12}}>{'--' + item.author + ',' + item.date}</Text>
</View>
)
}
return (
<Card title="Comments">
<FlatList
data={comments}
renderItem={renderCommentsItem}
keyExtractor={item => item.id.toString()}
/>
</Card>
)
}
class Dishdetail extends Component {
constructor(props) {
super(props)
this.state = {
favorites: []
}
}
markFavourite(dishId) {
this.setState({favorites: this.state.favorites.concat(dishId)})
}
//setup the navigation for the current class [Dishdetail]
static navigationOptions = {
title : 'Dish Details'
}
render(){
// pass or extract the dish id through the navigation
const dishId = this.props.navigation.getParam('dishId', '');
return (
<ScrollView>
<RenderDish dish={this.props.dishes.dishes[+dishId]}
favorites={this.state.favorites.some(el => el === dishId)}
onPress={() => this.markFavourite(dishId)}/>
<RenderComments comments={this.props.comments.comments.filter((comment) => comment.dishId === dishId)} />
</ScrollView>
)
}
}
export default connect(mapStateToProps)(Dishdetail);

How Can I touch overflow Middle Button on bottomTab navigation?

I want to Make TabNavigation Using react-navigation.
like that picture.
Here is picture my App. I want to Touch that 'red-section' But it is now work now
I want to active that section. Please tell me how can i do...
Middle Button is more bigger than others
this is my App.js Code. And I made AddButton Component.
const AppContainer = createStackNavigator(
{
default: createBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <AntDesign name="home" size={35} color={tintColor} />
}
},
Post: {
screen: () => null,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<TouchableOpacity size={150}
activeOpacity={1}
style={{
width:75,
height:75,
justifyContent: 'center',
alignItems: 'center',
height:80,
marginBottom:80
}}
>
<AddButton/>
</TouchableOpacity>
),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <MaterialIcons name="person-outline" size={35} color={tintColor} />
}
}
},
{
defaultNavigationOptions: {
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (navigation.state.key === 'Post') {
navigation.navigate('postModal')
} else {
defaultHandler()
}
}
},
tabBarOptions: {
activeTintColor: '#5A2AB7',
inactiveTintColor: '#404040',
showLabel: false,
style: { height: 80 },
}
}
),
postModal: {
screen: PostScreen
}
},
{
mode: 'modal',
headerMode: 'none',
}
)
const AuthStack = createStackNavigator({
Login: LoginScreen,
Register: RegisterScreen
})
export default createAppContainer(
createSwitchNavigator(
{
Loading: LoadingScreen,
App: AppContainer,
Auth: AuthStack
},
{
initialRouteName: "Loading"
}
)
);
here is AddButton.js
import React from 'react'
import {View, StyleSheet, Text, TouchableHighlight, Animated} from 'react-native'
import {FontAwesome5} from '#expo/vector-icons'
export default class AddButton extends React.Component {
render() {
return (
<View style={styles.button} underlayColor='#875EC1'>
<FontAwesome5 name="plus" size= {24} color="#FFF" />
</View>
)
}
}
const styles = StyleSheet.create({
button:{
backgroundColor:'#875EC1',
alignItems:'center',
justifyContent:'center',
width:72,
height:72,
borderRadius:36,
shadowColor:'#875EC1',
shadowRadius:5,
shadowOffset: {height:10},
shadowOpacity:0.3,
elevation:3
}
})

React Native Navigation Title

Apparently simple problem: the Header Title in react Navigation
Navigator file with my Bottom Tabs
const BottomTabNavigator = createMaterialBottomTabNavigator(
{
ToFind: {
screen: TopBarNavigator,
navigationOptions: {
title: "Discover",
tabBarIcon: (tabInfo) => {
return (
<Ionicons
name="md-search"
size={25}
color={tabInfo.tintColor} //prende lo stesso colore di tintcolor giù
/>
);
},
tabBarColor: "#27ae60",
activeColor: "white",
},
},
....
const Navigator = createStackNavigator({
BottomTabNavigator,
Detail: DetailScreen, // not visible but I need the navigation
Item: ItemDisplay, // not visible but I need the navigation
});
Now I try to set the name into the page (at the bottom)
MapScreen.navigationOptions = (navData) => {
return {
headerTitle: "Map",
};
};
Doing this I have the Bottom Tabs styled as I want and navigation but I CAN'T change the header title (navigation title) but I always see BottomTabNavigator
It looks really trick or I'm mistaking somewhere?
Any Idea?
Thanks
createMaterialBottomTabNavigator does not have header bar by default, but createStackNavigator has.
You can do something like this.
import React from "React";
import { createAppContainer, createStackNavigator } from "react-navigation";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen</Text>
</View>
);
}
}
const Tab1 = createStackNavigator({
S1: {
screen: ToFind
}
});
const Tab2 = createStackNavigator({
S2: {
screen: ToFind
}
});
export default createAppContainer(
createBottomTabNavigator({
Tab1,
Tab2
}, {
//CUSTOM CONFIG
initialRouteName: 'Tab1',
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Tab1') {
iconName = 'icon1';
} else if (routeName === 'Tab2') {
iconName = 'icon2';
}
return <Icon name={iconName} size={24} color={tintColor} />;
<Ionicons
name={iconName}
size={25}
color={tabInfo.tintColor} //prende lo stesso colore di tintcolor giù
/>
},
}),
tabBarOptions: {
activeTintColor: 'white',
inactiveTintColor: 'black',
showLabel: false,
style: {
backgroundColor: '#27ae60',
borderTopWidth: 0,
borderTopColor: '#27ae60',
},
},
});
);
Try these steps. Hope to fix your problem.
Create Your Bottom Tab Navigator :
const BottomTabNavigator = createMaterialBottomTabNavigator(
{
PageOne: {
screen: PageOneComponent,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Feather name="airplay" size={26} color={tintColor} />,
tabBarLabel: null,
barStyle: { backgroundColor: 'white', elevation: 0, }
},
},
PageTwo: {
screen: PageTwoComponent,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Feather name="search" size={25} color={tintColor}/>,
tabBarLabel: null,
barStyle: { backgroundColor: 'white', elevation: 0, }
}
},
MapViewLink: {
screen: MapView,
navigationOptions: {
tabBarIcon: <Feather name="map-pin" size={25} color={'green'} />,
tabBarOnPress: ({ navigation }) => {
navigation.navigate('MapView');
},
tabBarLabel: null
}
},
},
{
initialRouteName: 'PageOne',
activeColor: 'orange',
inactiveColor: 'grey',
labeled: false,
barStyle: { backgroundColor: 'white', elevation: 0, borderTopWidth: 1, borderTopColor: '#efefef' },
}
);
Create your StackNavigator and export the navigator
const StackNavigator = createStackNavigator({
// bottom tab navigator
BottomTabNavigator: {
screen: BottomTabNavigator,
navigationOptions: {
header: null
}
},
// MapView Page
MapView: {
screen: MapView,
navigationOptions: ({ navigation }) => ({
title: 'Hello World'
})
},
}, {
defaultNavigationOptions: ({navigation}) => ({
headerTitleAlign: 'center',
cardStyle: { backgroundColor: '#FFFFFF' },
headerTitleStyle: {
// the default styles you want to apply to header title
},
});
export default createAppContainer(StackNavigator);
In the end, put the navigator inside the main project file. e.g App.js

Update username in navigation drawer when login with diffrent user in react native

I am showing username in drawernavigator, but when I logged out and logged in again with a different user, the username is not updating, it's showing old username.
I am also using didFocus Listener but it is also not working please help
import React, { Component } from 'react';
import { View, Image,Text, TouchableOpacity,MenuImage,navigation,AsyncStorage, Alert } from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
import {
createDrawerNavigator,
createStackNavigator,
DrawerItems,
} from 'react-navigation';
import WalkThrow from '../pages/WalkThrow';
import Login from '../pages/Login';
import Register from '../pages/Register';
class NavigationDrawerStructure extends Component {
static propTypes = {
navigation: functionTypes.isRequired,
};
toggleDrawer = async() => {
this.props.navigationProps.openDrawer();
};
render() {
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={this.toggleDrawer.bind(this)}>
<Image
source={require('../assets/images/menu48.png')}
style={{ width: 25, height: 25, marginLeft: 15 }}
/>
</TouchableOpacity>
</View>
);
}
}
class NavigationImage extends Component {
toggleDrawer = async() => {
this.props.navigationProps.openDrawer();
};
render() {
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={this.toggleDrawer. bind(this)}>
<Image
source={require('../assets/images/user.png')}
style={{ width: 40, height: 40, marginRight:15 }}
/>
</TouchableOpacity>
</View>
);
}
}
class ShowUserName extends Component{
constructor(props) {
super(props);
this.state = {
getname:''
}
}
componentDidMount= async()=>{
let getname = await AsyncStorage.getItem('userName');
this.setState({getname:getname});
const { navigation } = this.props;
this.focusListener = navigation.addListener("didFocus", async() => {
let getname = await AsyncStorage.getItem('userName');
this.setState({getname:getname});
});
}
render() {
return (
<View>
<Text style={{color:'#fff',fontSize:23,padding:5}}>
{this.state.getname}
</Text>
</View>
);
}
}
const Logout= createStackNavigator({
Register:{
screen:Register,
navigationOptions:{
header: null,
},
},
Login: {
screen: Login,
navigationOptions:{
header: null,
}
},
ForgetPassword: {
screen: ForgetPassword,
navigationOptions:{
header: null,
}
},
initialRouteName: 'WalkThrow',
});
const Profile_StackNavigator = createStackNavigator({
Profile: {
initialRouteName: 'Profile',
screen:ChangeName,
navigationOptions: ({ navigation }) => ({
title: 'Profile',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#3598db',
shadowOpacity: 0,
elevation: 0,
},
headerTintColor: '#fff',
}),
}
});
const ChangePassword_StackNavigator = createStackNavigator({
ChangePassword: {
initialRouteName: 'WalkThrow',
screen:ChangePassword,
navigationOptions: ({ navigation }) => ({
title: 'Change Password',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#3598db',
shadowOpacity: 0,
elevation: 0,
},
headerTintColor: '#fff',
}),
},
});
const DashBoard_StackNavigator = createStackNavigator({
WalkThrow: {
screen: WalkThrow,
navigationOptions:{
header: null,
},
},
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#3598db',
height: 200,
alignItems: 'center',
justifyContent: 'center',
}}>
<Image
source={require('../assets/images/user.png')}
style={{ width:'36%', height: '50%' }}
/>
<ShowUserName/>
</View>
<DrawerItems {...props} />
</View>
)
export default createDrawerNavigator({
ChangePassword: {
screen: ChangePassword_StackNavigator,
initialRouteName: 'Logout',
navigationOptions: {
drawerLabel: 'Change Password',
drawerIcon: () => (
<Image
source={require('../assets/images/user48.png')}
style={{width: 25, height: 25, }}
/>
)
},
},
Logout: {
screen: Logout,
initialRouteName: 'Logout',
navigationOptions: {
drawerLabel: 'Logout',
drawerIcon: () => (
<Image
source={require('../assets/images/user48.png')}
style={{width: 25, height: 25,}}
/>
)
},
},
},
{
contentComponent: DrawerContent,
});
I am showing username in drawernavigator,but when i logged out and login again with different user the username is not updating,its showing old username.when different user login then show the username for those user
the issue is that this doesn't rerun because the drawer does not unmount
componentDidMount= async()=>{
let getname = await AsyncStorage.getItem('userName');
this.setState({getname:getname});
const { navigation } = this.props;
this.focusListener = navigation.addListener("didFocus", async() => {
let getname = await AsyncStorage.getItem('userName');
this.setState({getname:getname});
});
}
the bigger problem with the architecture of your app is that you' using asyncStorage as your state management it isa huge anti pattern and will make your app really slow and battery draining in the long run.
you have to use some sort of state management ie Context API or redux, then you get your userName straight form the global state it will make the app much faster and solve your problem and probably many others you are experiencing
then your render will look something like this without any need to to set the state again in a lifeCycle Method, you may also need a default depending where you declared the drawer
render() {
return (
<View>
<Text style={{color:'#fff',fontSize:23,padding:5}}>
{this.props.SOMEGLOBALCONTEXTHERE.username || ''}
</Text>
</View>
);
}

React-Navigation hide tabBar in StackNavigator inside a TabRouter

Having problem hiding the tabBar once we are inside StackNavigator which is inside TabRouter.
im using the navigatorOption, but it does not seem to be doing anything.
navigationOptions: {tabBarVisible: false}
can access expo.io from https://snack.expo.io/Sk4fQHAfZ
import React from 'react';
import {
Button,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {
createNavigator,
createNavigationContainer,
TabRouter,
addNavigationHelpers,
StackNavigator,
} from 'react-navigation';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<Text>{banner}</Text>
<Button
onPress={() => {
navigation.goBack(null);
}}
title="Go back"
/>
</ScrollView>
);
const NestedMyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<Text>{banner}</Text>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jane' })}
title="Go to a profile screen"
/>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Go to a photos screen"
/>
</ScrollView>
);
const MyNotificationsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const MyPhotosScreen = ({ navigation }) => {
let params = navigation.state.routes[navigation.state.index].params;
// let params = navigation.state.params;
return <MyNavScreen
banner={`${params.name}'s Photos`}
navigation={navigation}
/>
};
MyPhotosScreen.navigationOptions = {
title: 'Photos',
};
const MyProfileScreen = ({ navigation }) => {
let params = navigation.state.routes[navigation.state.index].params;
// let params = navigation.state.params;
return <MyNavScreen
banner={`${params.mode === 'edit' ? 'Now Editing ' : ''}${params.name}'s Profile`}
navigation={navigation}
/>
};
const CustomTabBar = ({ navigation }) => {
const { routes } = navigation.state;
return (
<View style={styles.tabContainer}>
{routes.map(route => (
<TouchableOpacity
onPress={() => navigation.navigate(route.routeName)}
style={styles.tab}
key={route.routeName}
>
<Text>{route.routeName}</Text>
</TouchableOpacity>
))}
</View>
);
};
const SimpleStack = StackNavigator({
NestedHome: {
screen: NestedMyNavScreen
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
navigationOptions: {tabBarVisible: false}
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
});
const CustomTabView = ({ router, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForState(navigation.state);
return (
<View style={styles.container}>
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
<CustomTabBar navigation={navigation} />
</View>
);
};
const CustomTabRouter = TabRouter(
{
Home: {
screen: SimpleStack,
path: '',
},
Notifications: {
screen: MyNotificationsScreen,
path: 'notifications',
},
Settings: {
screen: MySettingsScreen,
path: 'settings',
},
},
{
// Change this to start on a different tab
initialRouteName: 'Home',
}
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
);
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 0,
flexDirection: 'column',
justifyContent: 'space-between',
flex: 1
},
tabContainer: {
flexDirection: 'row',
height: 48,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
margin: 4,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 4,
},
});
export default CustomTabs;
Seems like its not working when your using your custom tabRouter.
I got it to work removing it : https://snack.expo.io/H1NmvXE5b
(Also in your expo link you've wrongly used {tabBar : {visible:false}}
You can try and style your tab bar buttons either in each screen in the navigationOptions
OR
you could do it the way its done here:
(Just for example sake from the native-base docs:)
export default MainScreenNavigator = TabNavigator(
{
LucyChat: { screen: LucyChat },
JadeChat: { screen: JadeChat },
NineChat: { screen: NineChat }
},
{
tabBarPosition: "bottom",
tabBarComponent: props => {
return (
<Footer>
<FooterTab>
<Button
vertical
active={props.navigationState.index === 0}
onPress={() => props.navigation.navigate("LucyChat")}>
<Icon name="bowtie" />
<Text>Lucy</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 1}
onPress={() => props.navigation.navigate("JadeChat")}>
<Icon name="briefcase" />
<Text>Nine</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 2}
onPress={() => props.navigation.navigate("NineChat")}>
<Icon name="headset" />
<Text>Jade</Text>
</Button>
</FooterTab>
</Footer>
);
}
}
));
The problem is that you can only set navigation options for the navigator that renders a given screen. The screen that you want to hide the tab bar on is rendered by a stacknavigator, which does not have a tabBarVisible navigation option.
This link to the docs explains in more detail:
https://reactnavigation.org/docs/en/navigation-options-resolution.html#a-stack-contains-a-tab-navigator-and-you-want-to-set-the-title-on-the-stack-header
The solution is to set the navigation options in your stackNavigator, which is rendered by the tabNavigator. You can use a function to vary the navigation option per screen. Below is an example from the docs:
https://reactnavigation.org/docs/en/navigation-options-resolution.html#a-stack-contains-a-tab-navigator-and-you-want-to-set-the-title-on-the-stack-header
Here's another simple example:
const HomeStack = createStackNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen
},
{
initialRouteName: "Home",
}
);
HomeStack.navigationOptions = ({ navigation }) => {
// get the name of the route
const { routeName } = navigation.state.routes[navigation.state.index];
if (routeName === 'Settings'){
tabBarVisible = false;
}
else{
tabBarVisible = true;
}
return {
tabBarVisible, // this now varies based on screen
tabBarLabel: "Search", // this is the same for all screens
};
};
export default createBottomTabNavigator(
{
HomeStack,
})