Related
I have been following guide at https://reactnavigation.org/docs/3.x/navigating-without-navigation-prop/. However, when I create the Navigation service as per given code snippet and attempt to set the toplevel navigator in my navigator component, It is not navigating to desire screen.
I want to navigate to the brandscreen.js when clicking on brand-logo from homescreen (want tp implement Shop by Brand) but not able to navigate.
App.js
import React, { Component } from 'react';
import { View, Text, StyleSheet,Image} from 'react-native';
import { DrawerItems,
createStackNavigator,
createDrawerNavigator,
createAppContainer,
createSwitchNavigator,
createBottomTabNavigator} from 'react-navigation'
import HomeScreen from './app/screen/HomeScreen';
import ProfileScreen from './app/screen/ProfileScreen';
import Orders from './app/screen/Orders';
import Notification from './app/screen/Notification';
import Logout from './app/screen/Logout';
import EditProfile from './app/screen/EditProfile'
import {Box} from 'react-native-design-utility'
import Address from './app/screen/Address'
import { Container,Header,Content, Body, Icon,Button} from 'native-base';
import BrandScreen from './app/screen/BrandScreen';
import NavigationService from './app/services/NavigationService'
const profileheader={
headerStyle:{
backgroundColor: '#3a455c',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}
class WelcomeScreen extends Component {
render() {
return (
<Box f={1} center>
<Button block light style={styles.btn} onPress={()=>this.props.navigation.navigate('Dashboard')}>
<Text style={{fontSize:16,color:'white',fontWeight:'bold'}}>Login</Text>
</Button>
<Button block light style={styles.btn} onPress={()=>this.props.navigation.navigate('Welcome')}>
<Text style={{fontSize:16,color:'white',fontWeight:'bold'}}>Sign Up</Text>
</Button>
</Box>
);
}
}
const ProfileStack=createStackNavigator({
Profile:{
screen:ProfileScreen,
navigationOptions:({navigation})=>{
return {
headerLeft:<Icon name="md-menu" style={{color:'white',marginLeft:10}} onPress={()=>navigation.toggleDrawer()}/>,
headerStyle:{
backgroundColor: '#3a455c',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}
}
},
EditProfile:{
screen:EditProfile,
navigationOptions:{...profileheader},
}
})
const ProfiletTabNavigator=createBottomTabNavigator({
Profile:{
screen:ProfileStack,
navigationOptions: {
tabBarLabel: 'Profile',
tabBarIcon: () =><Icon name="md-person" size={25} style={{fontSize: 20,paddingTop:5}}/>
}
},
Address:{
screen:Address,
navigationOptions: {
tabBarLabel: 'Saved Address',
tabBarIcon: () =><Icon name="md-bookmark" size={25} style={{fontSize: 20,paddingTop:5}}/>
}
},
},{
navigationOptions:({navigation})=>{
const {routeName}=navigation.state.routes[navigation.state.index]
return {
headerTitle: routeName,
header:null,
headerStyle: {
backgroundColor: '#3a455c',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}
}
})
const ProfileStackNavigator=createStackNavigator({
ProfiletTabNavigator:{
screen:ProfiletTabNavigator,
}
},{
defaultNavigationOptions:({navigation})=>{
return {
headerLeft:<Icon name="md-menu" style={{color:'white',marginLeft:10}} onPress={()=>navigation.toggleDrawer()}/>
}
}
});
const CustomDrawerContentComponent=(props)=>(
<Container>
<Header style={{height:130,backgroundColor:'#3a455c',marginTop:0}}>
<Body>
<Image name='person' style={styles.dImage}
source={require('./app/img/profile-image.jpg')}/>
</Body>
</Header>
<Content>
<DrawerItems {...props}/>
</Content>
</Container>
)
const HomeStack=createStackNavigator({
Home:{
screen:HomeScreen,
navigationOptions: {
header:null,
tabBarLabel: 'Home',
tabBarIcon: () => <Icon name="md-home" size={25} style={{fontSize: 20,paddingTop:5}}/>
},
Brand:BrandScreen
}
})
const AppDrawerNavigator=createDrawerNavigator ({
Home:{
screen:HomeStack,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: () =><Icon name="md-home" size={25} style={{fontSize: 20,paddingTop:5}}/>
}
},
Profile:{
screen:ProfileStackNavigator,
navigationOptions: {
drawerLabel: 'My Account',
drawerIcon: () =><Icon name="md-person" size={25} style={{fontSize: 20,paddingTop:5}}/>
}
},
Orders:Orders,
Notification:Notification,
Logout:Logout,
},{
initialRouteName:'Home',
contentComponent:CustomDrawerContentComponent,
})
const AppSwitchNavigator=createSwitchNavigator({
Welcome:WelcomeScreen,
Dashboard:AppDrawerNavigator,
})
const AppNavigator=createAppContainer(AppSwitchNavigator);
export default class App extends Component {
render() {
return (
<AppNavigator ref={r => NavigationService.setTopLevelNavigator(r)} />
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#2c3e50',
},
dImage:{
height:100,
width:100,
borderRadius:50,
},
btn:{
padding:10,
margin:10,
backgroundColor:'#273746',
borderRadius:4
}
});
NavigationService.js
let _navigator;
function setTopLevelNavigator( navigatorRef ){
_navigator = navigatorRef;
}
function navigate( routeName, params ){
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params
})
);
}
export default {
navigate,
setTopLevelNavigator,
};
BrandCard.js
//import liraries
import React, { Component } from 'react';
import {Image,TouchableOpacity,StyleSheet} from 'react-native'
import {Box,Text} from 'react-native-design-utility'
import NavigationService from '../services/NavigationService';
class BrandCard extends Component {
state={};
handlepress =()=>{
NavigationService.navigate('Brand',{ name: this.props.title});
};
render() {
const {title,image}=this.props;
return(
<TouchableOpacity onPress={this.handlepress} style={{flex:1}}>
<Box center f={1}>
<Box>
<Image source={image} style={{height:100,weight:100,resizeMode:'contain'}}
/>
</Box>
</Box>
</TouchableOpacity>
)
}
}
export default BrandCard;
The only thing you are doing wrong is you are using a route name "brand" which is not declared in your routes.
NavigationService.navigate('Brand',{ name: this.props.title});
Here replace "Brand" with your correct routename.
Hope this helps!
I am trying to navigate between different screens by pressing image components. Each different image leads to a different screen.
I am firstly trying to navigate by clicking 'meo.sudoeste.png' to 'meo_sw'. However whenever I press the image nothing happens. This is my HomeScreen.js:
import React from 'react';
import {View, Text, StyleSheet, TouchableOpacity, TextInput, ScrollView, Image} from 'react-native';
import * as firebase from 'firebase';
import Icon from 'react-native-vector-icons/Ionicons';
import { StackNavigator } from 'react-navigation';
export default class HomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = { }
}
render() {
return (
<View style={styles.screen}>
<View style={styles.container}>
<View>
<Icon name={"ios-search"} style={styles.icon}/>
</View>
<TextInput style={styles.inputBox}
underlineColorAndroid='rgba(0,0,0,0)'
placeholder="Procura aqui"
placeholderTextColor = "black"
selectionColor="black"
keyboardType="default"/>
</View>
<ScrollView style={styles.teste}>
<Text style={styles.festivais}>Recomendados</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.festivais_lista}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('meo_sw')}>
<Image source={require('../assets/meo_sudoeste.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('vodaf_coura')}>
<Image source={require('../assets/vodafone_coura.png')} style={styles.image} />
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('superR_superB')}>
<Image source={require('../assets/superbock_superrock.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('nos')}>
<Image source={require('../assets/nos_primavera.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('rock_in_rio')}>
<Image source={require('../assets/rock_in_rio.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('edp_cool_jazz')}>
<Image source={require('../assets/edp_cooljazz.png')} style={styles.image}/>
</TouchableOpacity>
</ScrollView>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
// I took this off because it is irrelevant.
});
Could you please help me?
This is my App.js, which contains the stack navigator
import React from 'react';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import {createBottomTabNavigator} from 'react-navigation-tabs'
import {Ionicons} from '#expo/vector-icons';
import ChatScreen from './screens/ChatScreen';
import PostScreen from './screens/PostScreen';
import NotificationScreen from './screens/NotificationScreen';
import ProfileScreen from './screens/ProfileScreen';
import LoadingScreen from './screens/LoadingScreen';
import LoginScreen from './screens/LoginScreen';
import RegisterScreen from './screens/RegisterScreen';
import HomeScreen from './screens/HomeScreen';
import firebaseConfig from './config';
import * as firebase from 'firebase';
import meo_sw from '../Eventos/Festivais/meo_sw';
const AppContainer = createStackNavigator(
{
default: createBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) => <Ionicons name='ios-home' size={30} color={tintColor}></Ionicons>
}
},
Chat: {
screen: ChatScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) => <Ionicons name='ios-chatboxes' size={30} color={tintColor}> </Ionicons>
}
},
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) => <Ionicons name='ios-home' size={30} color={tintColor} style={{
shadowColor:'#E9446A',
shadowOffset:{
width:0,
heigth:0,
shadowRadius:10,
shadowOpacity:0.3}}}></Ionicons>
}
},
Post: {
screen: PostScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) =>
<Ionicons name='ios-add-circle'
size={48} color={tintColor}>
</Ionicons>
}
},
Notification: {
screen: NotificationScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) => <Ionicons name='ios-notifications' size={30} color={tintColor}> </Ionicons>
}
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: ({tintColor}) => <Ionicons name='ios-person' size={30} color={tintColor}> </Ionicons>
}
}
},
{
defaultNavigationOptions:{
tabBarOnPress: ({navigation, defaultHandler}) => {
if (navigation.state.key === 'Post') {
navigation.navigate('postModal')
} else {
defaultHandler()
}
}
},
tabBarOptions: {
activeTintColor: '#FFA200',
inactiveTintColor: '#B8B8C4',
showLabel: false
}
}
),
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'
}
)
)
UPDATE
And this is my meo_sw.js :
import * as React from 'react'
import { View, Text, ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
export default function Meo() {
return (
<ScrollView>
<View style={styles.header}>
<Text style={styles.texto}>Meo Sudoeste</Text>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
header:{
width:'100%',
height:90,
paddingTop:36,
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center'
},
texto:{
color:'white',
fontSize: 18
}
});
looks like you're trying to navigate to meo_sw which is not registered in your Stack Navigator. Do you want to try updating your code as follows:
import meo_sw from "./meo_sw"
const AppContainer = createStackNavigator(
{
meo_sw: meo_sw,
default:
... // Your existing code.
}
That should register it as a screen you can navigate to.
Create a separate StackNavigator for HomeScreen & inert your meo_sw into it
const HomeStack = createStackNavigator({
Home: { screen: HomeScreen },
meo_sw : { screen: meo_sw },
});
Then change your TabNavigator to handle HomeStack
Home: {
screen: HomeStack,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Ionicons name='ios-home' size={30} color={tintColor}></Ionicons>
}
Check A stack navigator for each tab for more informations or check Complex Navigation example with react navigation.
Hope this helps you. Feel free for doubts.
Here is a very minimal example you can customize accordingly.
https://snack.expo.io/#raajnadar/navigate-on-press-of-image-inside-stack
Final route config
import React from 'react';
import { Image, Text, TouchableWithoutFeedback, View } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { Ionicons } from '#expo/vector-icons';
import MeoSw from './MeoSw';
function HomeScreen({ navigation }) {
return (
<View>
<Text>Home Screen</Text>
<TouchableWithoutFeedback onPress={() => navigation.navigate('MeoSw')}>
<Image
source={require('./assets/snack-icon.png')}
style={{
width: 200,
height: 200,
marginTop: 40,
alignSelf: 'center',
}}
/>
</TouchableWithoutFeedback>
</View>
);
}
function ChatScreen() {
return (
<View>
<Text>Chat Screen</Text>
</View>
);
}
const Stack = createStackNavigator({
MeoSw: MeoSw
})
const AppContainer = createBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-home" size={30} color={tintColor} />
),
},
},
Chat: {
screen: ChatScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Ionicons name="ios-chatboxes" size={30} color={tintColor}>
{' '}
</Ionicons>
),
},
},
Stack: Stack
},
{
defaultNavigationOptions: {
tabBarOnPress: ({ navigation, defaultHandler }) => {
if (navigation.state.key === 'Post') {
navigation.navigate('postModal');
} else {
defaultHandler();
}
},
},
tabBarOptions: {
activeTintColor: '#FFA200',
inactiveTintColor: '#B8B8C4',
showLabel: false,
},
}
);
export default createAppContainer(AppContainer);
I am implementing react-navigation-drawer from React Navigation Library. But facing problem related to header. The header bar is not showing in any of the screens.
This is my App.js
import React from "react";
import { StyleSheet, ScrollView, View } from "react-native";
//import DrawerNavigator from "./navigation/DrawerNavigator";
import { Platform, Dimensions } from "react-native";
import { createAppContainer } from "react-navigation";
import { createDrawerNavigator } from "react-navigation-drawer";
import Home from "./components/home";
import Contact from "./components/contact";
const WIDTH = Dimensions.get("window").width;
const RouteConfigs = {
Home: {
screen: Home
},
Contact: {
screen: Contact
}
};
const DrawerNavigatorConfig = {
drawerWidth: WIDTH * 0.75,
drawerType: "both",
initialRouteName: "Home"
};
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const MyApp = createAppContainer(DrawerNavigator);
export default class App extends React.Component {
render() {
return <MyApp />;
}
}
And this is my home screen
import React, { Component } from "react";
import { View, Image, Text, StyleSheet, ScrollView } from "react-native";
import { FontAwesomeIcon } from "#fortawesome/react-native-fontawesome";
import { faTruck, faHome } from "#fortawesome/free-solid-svg-icons";
class Home extends Component {
static navigationOptions = {
headerTitle: "Home",
drawerIcon: ({ tintColor }) => <FontAwesomeIcon size={25} icon={faHome} />
};
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5F5F5",
flexDirection: "column"
},
icon: {
width: 24,
height: 24
}
});
export default Home;
Can anyone help me. Thanks in advance!!!
#hongdeveloper this is a simple example solution for react navigation 5:
function Root() {
return (
<Stack.Navigator>
<Stack.Screen options={{title: "Profile"}} name="Profile" component={Profile} />
<Stack.Screen options={{title: "Settings"}} name="Settings" component={Settings} />
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Root" component={Root} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You can find about the navigation to a screen in a nested navigator in docs and you can try this example on Snack
The drawer navigator does not contain headers. Stack navigators must be configured to display headers.
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const Root = createStackNavigator({
Main: { screen : DrawerNavigator}
},
{
defaultNavigationOptions : ({ navigation }) => ({
title: "Screen"
})
})
const Stacks = createAppContainer(Root)
export default Stacks;
Since December 2020 you can now use the headerShown: true setting in screenOptions of your Drawer.Navigator to show the header in React Navigation 5.
See more about this issue here: https://github.com/react-navigation/react-navigation/issues/1632
See the commit and comments about the new feature in React Navigation 5 here
https://github.com/react-navigation/react-navigation/commit/dbe961ba5bb243e8da4d889c3c7dd6ed1de287c4
Late reply, But I did it with the below code.
I created separate stack navigators for each screen and after that added all the stack navigators in the drawer navigator.
The good thing is it is fully customized.
Please see my code below.
const WIDTH = Dimensions.get('window').width;
const HomeNavigator = createStackNavigator(
{
Home: Home
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerStyle: {
backgroundColor: '#1e89f4'
},
headerTitle: 'Knowledge Woledge',
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
flex: 1
},
headerLeft: (
<View style={{ paddingLeft: 13 }}>
<FontAwesomeIcon
size={25}
color='#fff'
icon={faBars}
onPress={() => navigation.openDrawer()}
/>
</View>
),
headerRight: <View />
};
}
}
);
const DetailNavigator = createStackNavigator(
{
PostDetail: PostDetail
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerStyle: {
backgroundColor: '#1e89f4'
},
headerTitle: () => {
return (
<Text
style={{
color: '#fff',
fontWeight: 'bold',
textAlign: 'center',
flex: 1,
fontSize: 20
}}
>
{navigation.getParam('headerTitle')}
</Text>
);
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
flex: 1
},
headerLeft: (
<View style={{ paddingLeft: 13 }}>
<FontAwesomeIcon
size={25}
color='#fff'
icon={faArrowLeft}
onPress={() => navigation.goBack(null)}
/>
</View>
),
headerRight: <View />
};
}
}
);
Assigned this in a const
const RouteConfigs = {
Home: {
screen: HomeNavigator,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<FontAwesomeIcon size={20} color={tintColor} icon={faHome} />
)
}
},
Detail: {
screen: DetailNavigator,
navigationOptions: {
drawerLabel: () => {
return null;
}
}
}
};
And finally, create a drawer navigator with this.
const DrawerNavigatorConfig = {
drawerWidth: WIDTH * 0.75,
drawerType: 'both',
initialRouteName: 'Home'
};
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const Stacks = createAppContainer(DrawerNavigator);
export default Stacks;
I'm trying to develop an app to understand the react native basics. I'm usin react navigation and I would like to see menu in every page of my app. I've developed someting like;
-StackNavigtor
-Login Screen
-DrawerNagivation
-Screen1
-Screen2
However, inner drawer's components can not benefit from the stacking feature. What's the best way of obtaining drawer navigation with stack navigator in order to obtain menu in every page of my app.
Thanks.
Yes you can follow the following step.
App.js
import React, {Component} from 'react';'
import {Platform, StyleSheet, Text, View} from 'react-native';
import { createStackNavigator } from 'react-navigation';
import Login from './src/authScreen/login/Login';
import DrawerNavigator from './src/navigation/drawerNavigation/DrawerNavigator';
export default class App extends Component{
render() {
return (
<AppStackNavigator />
);
}
}
const AppStackNavigator = createStackNavigator({
Login:{
screen:Login
},
DrewerNav:{
screen:DrawerNavigator
}
},
navigationOptions={
headerMode:'none'
})
then create src folder and create DrawerNavigator.js . and Enter the following code.
import React from 'react' import { StyleSheet, Text, View, SafeAreaView, ScrollView, Dimensions, Image} from 'react-native';
import { createDrawerNavigator, DrawerItems } from 'react-navigation';
import Icon from 'react-native-vector-icons/FontAwesome5';import DrawerScreen1
from '../../screens/drawerScreen/DrawerScreen1' import DrawerScreen2
from '../../screens/drawerScreen/DrawerScreen2' import DrawerScreen3
from '../../screens/drawerScreen/DrawerScreen3' // import { Right }
from 'native-base';
const CustomDrawerComponent = (props)=>( <SafeAreaView>
<View style={{height:150, backgroundColor:'white', alignItems:'center', justifyContent:'center'}}>
<Image source={require('../../Images/user.jpg')} style={{height:120, width:120, borderRadius:60}} />
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView> </SafeAreaView> )
export default createDrawerNavigator(>
DrawerScreen1: {
screen: DrawerScreen1,
navigationOptions: {
drawerLabel: 'DrawerScreen1',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} },
DrawerScreen2: {
screen: DrawerScreen2,
navigationOptions: {
drawerLabel: 'DrawerScreen2',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} },
DrawerScreen3: {
screen: DrawerScreen3,
navigationOptions: {
drawerLabel: 'DrawerScreen3',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} }, }, { drawerPosition :"right", contentComponent:CustomDrawerComponent
});
Here CustomDrawerComponent add a Drawer Icon.
and add the login.js
import React, { Component } from 'react';
import {View,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import { Container, Header, Content, Button, Text } from 'native-base';
class Login extends Component{
constructor(props){
super(props);
}
loginHandler=()=>{
this.props.navigation.navigate('DrewerNav')
}
render(){
return(
<View style={styles.container}>
<Text> Login </Text>
<View style={{alignItems:'center'}}>
<Button onPress={this.loginHandler}>
<Text>Click Me!</Text>
</Button>
</View>
</View>
)
}
}
export default Login;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Further more: you can refer https://github.com/ChanakaUOMIT/React-Native-Root-boiler-plate/tree/master this project.. here also add Stack navigation, Tab Navigation and Drawer navigation in one project.
import 'react-native-gesture-handler';
import * as React from 'react';
import {View, TouchableOpacity, Image} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createDrawerNavigator} from '#react-navigation/drawer';
import LoginPage from './src/pages/LoginPage';
import SecondPage from './src/pages/SecondPage';
import ThirdPage from './src/pages/ThirdPage';
// Import Custom Sidebar
import CustomSidebarMenu from './src/pages/CustomSidebarMenu';
import SignUpPage from './src/pages/SignUp';
import Home from './src/pages/Home';
import VendingMachineList from './src/pages/VendingMachineList';
import ProductList from './src/pages/ProductList';
import ProductDetails from './src/pages/ProductDetails';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const NavigationDrawerStructure = (props) => {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={toggleDrawer}>
<Image
source={require('./src/assets/image/Vector.png')}
style={{width: 30, height: 20, marginLeft: 5}}
/>
</TouchableOpacity>
<TouchableOpacity onPress={toggleDrawer}>
<Image
source={require('./src/assets/image/track-fresh.png')}
style={{width: 30, height: 20, marginLeft: 5}}
/>
</TouchableOpacity>
</View>
);
};
function firstScreenStack({navigation}) {
return (
<Stack.Navigator initialRouteName="LoginPage">
<Stack.Screen
name="LoginPage"
component={LoginPage}
options={{
title: 'First Page', //Set Header Title
headerLeft: () => (
<NavigationDrawerStructure
navigationProps={navigation}
/>
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerShown:false,
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
<Stack.Screen
name="SignUpPage"
component={SignUpPage}
options={{
title: 'First Page', //Set Header Title
headerLeft: () => (
<NavigationDrawerStructure
navigationProps={navigation}
/>
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerShown:false,
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
</Stack.Navigator>
);
}
function HomeStack({navigation}) {
return (
<Stack.Navigator
initialRouteName="VendingMachineList"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: {
backgroundColor: '#fff', //Set Header color
},
headerTintColor: '#000', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}>
<Stack.Screen
name="HomePage"
component={Home}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ProductList"
component={ProductList}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ProductDetails"
component={ProductDetails}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="VendingMachineList"
component={VendingMachineList}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ThirdPage"
component={ThirdPage}
options={{
title: 'Third Page', //Set Header Title
}}
/>
</Stack.Navigator>
);
}
function secondScreenStack({navigation}) {
return (
<Stack.Navigator
initialRouteName="SecondPage"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}>
<Stack.Screen
name="SecondPage"
component={SecondPage}
options={{
title: 'Second Page', //Set Header Title
}}
/>
<Stack.Screen
name="ThirdPage"
component={ThirdPage}
options={{
title: 'Third Page', //Set Header Title
}}
/>
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: {marginVertical: 5},
}}
drawerContent={(props) => <CustomSidebarMenu {...props} />}>
<Drawer.Screen
name="LoginPage"
options={{drawerLabel: 'First page Option',swipeEnabled:false}}
component={firstScreenStack}
/>
<Drawer.Screen
name="Home"
options={{drawerLabel: 'Second page Option'}}
component={HomeStack}
/>
<Drawer.Screen
name="SecondPage"
options={{drawerLabel: 'Second page Option'}}
component={secondScreenStack}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
export default App;
I have created a tabbed view with three tabs based on RNE (React native elements demo app). I had to disable the drawernavigator from the middle tab because it doesn't work to click a link in the drawer and then click the drawer again back to the middle tab view because then it crashes. From the left and right tab it works and I can't understand why this is the case. I'm just trying to open a view but since I am using react navigation it doesn't work. I use a fancy DrawerNavigator, a cool TabNavigator and a nifty StackNavigator instead of keeping it simple and I get error message trying to navigate from the DrawerNavigator to the TabNavigator.
The App.js
/**
* React Native App
*/
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View, Image, Dimensions, AppRegistry
} from 'react-native';
import { DrawerNavigator, DrawerItems,NavigationActions } from 'react-navigation';
import Components from './src/drawer/components';
import Ratings from './src/drawer/ratings';
import Pricing from './src/drawer/pricing';
import Login from './src/drawer/login';
import Profile from './src/drawer/profile';
import Lists from './src/drawer/lists';
const SCREEN_WIDTH = Dimensions.get('window').width;
const CustomDrawerContentComponent = props => {
return(
<View style={{ flex: 1, backgroundColor: '#43484d' }}>
<View
style={{ marginTop: 40, justifyContent: 'center', alignItems: 'center' }}
>
<Image
source={require('./src/images/logo.png')}
style={{ width: SCREEN_WIDTH * 0.57 }}
resizeMode="contain"
/>
</View>
<View style={{marginLeft: 10}}>
<DrawerItems {...props} />
</View>
</View>
)};
const MainRoot = DrawerNavigator(
{
Login: {
path: '/login',
screen: Login
},
Profile: {
path: '/profile',
screen: Profile
},
/* Lists: {
path: '/lists',
screen: Lists
},*/
Components: {
path: '/components',
screen: Components,
},
/* Ratings: {
path: '/ratings',
screen: Ratings,
},*/
Pricing: {
path: '/pricing',
screen: Pricing,
}
},
{
initialRouteName: 'Components',
contentOptions: {
activeTintColor: '#548ff7',
activeBackgroundColor: 'transparent',
inactiveTintColor: '#ffffff',
inactiveBackgroundColor: 'transparent',
labelStyle: {
fontSize: 15,
marginLeft: 0,
},
},
drawerWidth: SCREEN_WIDTH * 0.8,
contentComponent: CustomDrawerContentComponent,
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
}
);
export default MainRoot;
My drawer navigator.
/**
* React Native App
*/
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View, Image, Dimensions, AppRegistry
} from 'react-native';
import { DrawerNavigator, DrawerItems } from 'react-navigation';
import Components from './src/drawer/components';
import Ratings from './src/drawer/ratings';
import Pricing from './src/drawer/pricing';
import Login from './src/drawer/login';
import Profile from './src/drawer/profile';
import Lists from './src/drawer/lists';
const SCREEN_WIDTH = Dimensions.get('window').width;
const CustomDrawerContentComponent = props => (
<View style={{ flex: 1, backgroundColor: '#43484d' }}>
<View
style={{ marginTop: 40, justifyContent: 'center', alignItems: 'center' }}
>
<Image
source={require('./src/images/logo.png')}
style={{ width: SCREEN_WIDTH * 0.57 }}
resizeMode="contain"
/>
</View>
<View style={{marginLeft: 10}}>
<DrawerItems {...props} />
</View>
</View>
);
const CustomDrawerContentComponent2 = (props) => {
const nav = props.nav;
return (<View>
<ScrollView>
<DrawerItems
{...props}
onItemPress = {
({ route, focused }) =>
{
props.onItemPress({ route, focused })
console.log("item pressed");
}
}
/>
</ScrollView>
</View>)
};
const MainRoot = DrawerNavigator(
{
Login: {
path: '/login',
screen: Login
},
Profile: {
path: '/profile',
screen: Profile
},
Lists: {
path: '/lists',
screen: Lists
},
Components: {
path: '/components',
screen: Components,
},
/* Ratings: {
path: '/ratings',
screen: Ratings,
},*/
Pricing: {
path: '/pricing',
screen: Pricing,
}
},
{
initialRouteName: 'Components',
contentOptions: {
activeTintColor: '#548ff7',
activeBackgroundColor: 'transparent',
inactiveTintColor: '#ffffff',
inactiveBackgroundColor: 'transparent',
labelStyle: {
fontSize: 15,
marginLeft: 0,
},
},
drawerWidth: SCREEN_WIDTH * 0.8,
contentComponent: CustomDrawerContentComponent,
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
}
);
export default MainRoot;
My Tab Navigator.
import React from 'react';
import { TabNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
import ButtonsTab from '../tabs/buttons';
import ListsTab from '../tabs/lists';
import InputTab from '../tabs/input';
import FontsTab from '../tabs/fonts';
import DetailedTrends from '../views/lists_home'
const Components = TabNavigator(
{
ButtonsTab: {
screen: ButtonsTab,
path: '/buttons',
navigationOptions: {
tabBarLabel: 'Add',
tabBarIcon: ({ tintColor, focused }) => (
<Icon
name={focused ? 'camera' : 'camera'}
size={30}
type="material-community"
color={tintColor}
/>
),
},
},
ListsTab: {
screen: ListsTab,
path: '/lists',
navigationOptions: {
tabBarLabel: 'Ads',
tabBarIcon: ({ tintColor, focused }) => (
<Icon name="list" size={30} type="entypo" color={tintColor} />
),
},
},
/* FontsTab: {
screen: FontsTab,
path: '/fonts',
navigationOptions: {
tabBarLabel: 'On map',
tabBarIcon: ({ tintColor, focused }) => (
<Icon
name={focused ? 'map-marker-outline' : 'map-marker-outline'}
size={30}
type="material-community"
color={tintColor}
/>
),
},
},*/
InputTab: {
screen: InputTab,
path: '/input',
navigationOptions: {
tabBarLabel: 'My activity',
tabBarIcon: ({ tintColor, focused }) => (
<Icon
name={focused ? 'emoticon-cool' : 'emoticon-neutral'}
size={30}
type="material-community"
color={tintColor}
/>
),
},
},
},
{
initialRouteName: 'ListsTab',
animationEnabled: false,
swipeEnabled: true,
// Android's default option displays tabBars on top, but iOS is bottom
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#e91e63',
// Android's default showing of icons is false whereas iOS is true
showIcon: true,
},
}
);
Components.navigationOptions = {
drawerLabel: 'Components',
drawerIcon: ({ tintColor }) => (
<Icon
name="settings"
size={30}
iconStyle={{
width: 30,
height: 30
}}
type="material"
color={tintColor}
/>
),
};
export default Components;
If I now press "Components" in the Drawer Navigator to navigate to the components view, my app crashes.
"There is no route defined for key ButtonsTab."
What is the purpose of this error?
How can I troubleshoot this? Why is it complaining about ButtonsTab?
Error: There is no route defined for key ButtonsTab.
Must be one of: 'Home','Lists_Detail'
This error is located at:
in DrawerView (at DrawerNavigator.js:88)
in Unknown (at createNavigator.js:13)
in Navigator (at createNavigationContainer.js:226)
in NavigationContainer (at renderApplication.js:35)
in RCTView (at View.js:78)
in View (at AppContainer.js:102)
in RCTView (at View.js:78)
in View (at AppContainer.js:122)
in AppContainer (at renderApplication.js:34)
getScreenForRouteName
If I add a navigator to lists.js it almost works but still incomprehensible, unnecessary and wrong. Why do they make a framework where you can't navigate between screens?
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
import ListsHome from '../views/lists_home';
import ListsDetails from '../views/lists_detail';
import ButtonsTab from '../tabs/buttons';
const ListsTabView = ({ navigation }) => (
<ListsHome banner="Lists" navigation={navigation} />
);
const ListsDetailTabView = ({ navigation }) => (
<ListsDetails banner="Lists Detail" navigation={navigation} />
);
const ListsTab = StackNavigator({
Home: {
screen: ListsTabView,
path: '/',
navigationOptions: ({ navigation }) => ({
title: 'Lists',
headerLeft: (
<Icon
name="menu"
size={30}
type="entypo"
style={{ paddingLeft: 10 }}
onPress={() => navigation.navigate('DrawerOpen')}
/>
),
}),
},
Lists_Detail: {
screen: ListsDetailTabView,
path: 'lists_detail',
navigationOptions: {
title: 'Lists Detail',
},
}, ButtonsTab: {
screen: ListsTabView,
path: '/',
navigationOptions: ({ navigation }) => ({
title: 'Lists',
headerLeft: (
<Icon
name="menu"
size={30}
type="entypo"
style={{ paddingLeft: 10 }}
onPress={() => navigation.navigate('DrawerOpen')}
/>
),
}),
},
});
export default ListsTab;
You can use this sample project which I made to demonstrate StackNavigator, TabNavigator and DrawerNavigator working together.
github.com/paraswatts/DrawerNavigatorReactNative
I hope it helps.