I have just implemented an Auth stack and having an issue with my TabNavigator - when I click my second "Favourites" tab which is in my tab navigator and referenced the MainNavigator within my switch I get the message There is no route named 'Favourites' in the navigator with the key 'Dashboard. Must be one of: 'Dashboard, Admin'. This was working perfectly fine before I introduced switch navigator and had MainNavigator in my appContainer. Any clues?
import React from "react";
import { Platform, Text } from "react-native";
import { createAppContainer, createSwitchNavigator} from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createDrawerNavigator } from "react-navigation-drawer";
import { createBottomTabNavigator } from "react-navigation-tabs";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";
//Components
import DashboardScreen from "../screens/DashboardScreen";
import MapScreen from "../screens/MapScreen";
import VenueOverviewScreen from "../screens/VenueOverviewScreen";
import VenueDetailScreen from "../screens/VenueDetailScreen";
import QRCodeScanScreen from "../screens/QRCodeScanScreen";
import FavouritesScreen from "../screens/FavouritesScreen";
import AdminVenueScreen from "../screens/admin/AdminVenueScreen";
import AdminUserListScreen from "../screens/admin/AdminUserListScreen";
import AdminUserDetailScreen from "../screens/admin/AdminUserDetailScreen";
import AuthScreen from "../screens/auth/AuthScreen";
//Misc
import Colors from "../constants/Colors";
import { Ionicons } from "#expo/vector-icons";
//Default Nav
const defaultNavOptions = {
headerStyle: {
backgroundColor: Colors.brownPrimaryDark
},
headerTitleStyle: {
fontFamily: "roboto-regular"
},
headerTintColor: "white"
};
//Default Admin
const defaultAdminNavOptions = {
headerStyle: {
backgroundColor: Colors.greenPrimary
},
headerTitleStyle: {
fontFamily: "roboto-regular"
},
headerTintColor: "white"
};
//Main Stack
const HomeNavigator = createStackNavigator(
{
Dashboard: DashboardScreen,
Map: MapScreen,
Venues: VenueOverviewScreen,
VenueDetail: VenueDetailScreen,
},
{
defaultNavigationOptions: defaultNavOptions
}
);
//Fav Stack
const FavNavigator = createStackNavigator(
{
Favourites: FavouritesScreen
},
{
defaultNavigationOptions: defaultNavOptions
}
);
//AdminStack
const AdminNavigator = createStackNavigator(
{
Admin: AdminVenueScreen,
AdminUserList: AdminUserListScreen,
AdminUserDetail: AdminUserDetailScreen,
QRCodeScan: QRCodeScanScreen
},
{
defaultNavigationOptions: defaultAdminNavOptions
}
);
//Tab Config
const tabScreenConfig = {
Home: {
screen: HomeNavigator,
navigationOptions: {
tabBarLabel:
Platform.OS === "android" ? (
<Text style={{ fontFamily: "roboto-regular" }}>Dashboard</Text>
) : (
"Dashboard"
),
tabBarIcon: tabInfo => {
return <Ionicons name="ios-home" size={23} color={tabInfo.tintColor} />;
},
//tabBarColor: Colors.greyDark, //only shifting effect
}
},
Favourites: {
screen: FavNavigator,
navigationOptions: {
tabBarLabel:
Platform.OS === "android" ? (
<Text style={{ fontFamily: "roboto-regular" }}>Favourties</Text>
) : (
"Favourties"
),
tabBarIcon: tabInfo => {
return <Ionicons name="ios-star" size={23} color={tabInfo.tintColor} />;
},
//tabBarColor: Colors.greenPrimary //only shifting effect onPress
}
}
};
const TabNavigator =
Platform.OS === "android"
? createMaterialBottomTabNavigator(tabScreenConfig, {
activeTintColor: Colors.brownSecondaryLight,
shifting: true,
barStyle: { backgroundColor: '#eee' },
activeColor: Colors.greyDarker,
inactiveColor:'#ccc',
})
: createBottomTabNavigator(tabScreenConfig, {
tabBarOptions: {
labelStyle: {
fontFamily: "roboto-regular",
fontSize: 15
},
activeTintColor: Colors.greenPrimary,
}
});
const MainNavigator = createDrawerNavigator(
{
Dashboard: {
screen: TabNavigator,
navigationOptions: {
drawerLabel: "Dashboard",
drawerIcon: drawerConfig => (
<Ionicons
name="ios-home"
size={23}
color={drawerConfig.tintColor}
/>
)
}
},
Admin: {
screen: AdminNavigator,
navigationOptions: {
drawerLabel: "Admin",
drawerIcon: drawerConfig => (
<Ionicons
name="ios-lock"
size={23}
color={drawerConfig.tintColor}
/>
)
}
}
},
{
contentOptions: {
activeTintColor: Colors.greenPrimary,
itemsContainerStyle: {
marginVertical: 0
},
iconContainerStyle: {
opacity: 1
}
},
drawerPosition: "right",
}
);
const AuthNavigator = createStackNavigator(
{
Auth: AuthScreen
},
{
headerMode: "none",
navigationOptions: {
headerVisible: false
}
}
);
const MainAuthNavigator = createSwitchNavigator({
Auth: AuthNavigator,
Dashboard: MainNavigator, //User
});
export default createAppContainer(MainAuthNavigator);
try changing the key dashboard. You use it everywhere (three times)! just try Dashboard1, Dashboard2, etc
const MainAuthNavigator = createSwitchNavigator({
Auth: AuthNavigator,
Dashboard2: MainNavigator,
});
Related
I am new to react native and am trying to create a tabbar using createBottomTabNavigator. I would like each tab to have its own icon.
I have followed the following tutorial which uses FontAwesome to display the tab icon.
Tutorial
When I run my app in the iso simulator the tabs display but the icons don't.
Here is my code
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Icon from "react-native-vector-icons/FontAwesome5";
import HomeScreen from './HomeScreen';
import SecondActivity from './second';
const TabNavigator = createBottomTabNavigator({
Home: { screen: HomeScreen,
defaultNavigationOptions: {
tabBarIcon: ({tintColor}) =>
<Icon name="home" size={25} color={tintColor} />
}
},
Events: { screen: SecondActivity,
defaultNavigationOptions: {
tabBarIcon: ({tintColor}) =>
<Icon name="chart-bar" size={25} color={tintColor} />
}
}
}
);
const MyStack = createStackNavigator({
Tabs: {
screen: TabNavigator
},
Home: {
screen: HomeScreen
},
Events: {
screen: SecondActivity
}
},
{
initialRouteName: 'Tabs',
}
);
export default createAppContainer(MyStack);
How do I get the icons to display?
I have a solution for you that is a bit different that what you did in there .. so
const config = Platform.select({
web: { headerMode: "screen" },
default: {}
})
const HomeStack = createStackNavigator(
{
Home: HomeScreen
},
config
)
HomeStack.navigationOptions = {
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === "ios" ? "ios-calendar" : "md-calendar"}
/>
)
}
HomeStack.path = ""
and them you can do like this in createBottomTabNavigator
const tabNavigator = createBottomTabNavigator(
{
HomeStack,
},
{
activeColor: '#000'
}
// You can import Ionicons from #expo/vector-icons if you use Expo or
// react-native-vector-icons/Ionicons otherwise.
import Ionicons from 'react-native-vector-icons/Ionicons';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
export default createBottomTabNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen,
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let IconComponent = Ionicons;
let iconName;
if (routeName === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
// Sometimes we want to add badges to some icons.
// You can check the implementation below.
IconComponent = HomeIconWithBadge;
} else if (routeName === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// You can return any component that you like here!
return <IconComponent name={iconName} size={25} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
},
}
);
Link : https://snack.expo.io/#react-navigation/basic-tabs-v3
Link : https://reactnavigation.org/docs/en/tab-based-navigation.html
I'm adding in the react-navigation header a drawerMenuButton to open the Drawer Menu.
The icon appears normally but when pressed returns the error quoted.
import React from 'react';
import { View, Dimensions } from 'react-native';
import { Button, Icon } from 'native-base';
import { createAppContainer, createStackNavigator, createDrawerNavigator } from 'react-navigation';
...
const DrawerConfig = {
drawerWidth: Dimensions.get('window').width * 0.75,
contentComponent: ({ navigation }) => {
return(<MenuDrawer navigation={navigation} />)
}
}
const HomeNavigator = createStackNavigator ({
...
}, {
defaultNavigationOptions: ({ navigation }) => {
return {
headerTitleStyle: {
fontWeight: 'bold'
},
headerLeft: (
<Button transparent onPress={() => this.props.navigation.toggleDrawer()}>
<Icon name='menu' style={{color: '#FFF'}} />
</Button>
),
headerRight: (
<HomeIcon navigation={navigation} />
),
headerStyle: {
backgroundColor: '#b80003'
},
headerTintColor: '#FFF'
}
}
});
const DrawerNavigator = createDrawerNavigator (
{
'Principal': {
screen: HomeNavigator
},
'Sobre o Aplicativo': {
screen: InformationApp
},
'Sobre os Responsáveis': {
screen: Team
},
'Sobre o Projeto': {
screen: Project
},
'Política e Termos': {
screen: Policy
}
},
DrawerConfig
);
const AppDrawerContainer = createAppContainer(DrawerNavigator);
export default AppDrawerContainer;
It is important to note that for screens belonging to const DrawerNavigator = createDrawerNavigator I am using the same code above to render drawerMenuButton and it is working normally, the error occurs only on const screens HomeNavigator = createStackNavigator.
Change your code like this
onPress={() => navigation.toggleDrawer()}>
In my React- Native project , I have App.js file as my default class. In this is class I have used DrawerNavigation. Here I have provided the code for my App.js class-
App.js
import React, { Component } from 'react';
import { View, Image, TouchableOpacity } from 'react-native';
import {
createDrawerNavigator,
createStackNavigator,
createAppContainer,
} from 'react-navigation';
import Screen1 from './pages/Screen1';
import Screen2 from './pages/Screen2';
import Screen3 from './pages/Screen3';
class NavigationDrawerStructure extends Component {
toggleDrawer = () => {
this.props.navigationProps.toggleDrawer();
};
render() {
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={this.toggleDrawer.bind(this)}>
{/*Donute Button Image */}
<Image
source={require('./image/drawer.png')}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
}
const FirstActivity_StackNavigator = createStackNavigator({
First: {
screen: Screen1,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 1',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
const Screen2_StackNavigator = createStackNavigator({
Second: {
screen: Screen2,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 2',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
const Screen3_StackNavigator = createStackNavigator({
Third: {
screen: Screen3,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 3',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
const DrawerNavigatorExample = createDrawerNavigator({
Screen1: {
//Title
screen: FirstActivity_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 1',
},
},
Screen2: {
//Title
screen: Screen2_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 2',
},
},
Screen3: {
//Title
screen: Screen3_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 3',
},
},
});
export default createAppContainer(DrawerNavigatorExample);
Now, the problem is I want to make another class as my default class and from that class I want to import App.js and then lauch the App.js class. But in the App.js class I already have one export-
export default createAppContainer(DrawerNavigatorExample);
And in React-native it doesn't allow me to export multiple modules.
So, if I want to Export the App.js file and use it inside the View of another class, then how I can do that?
You can only export one module as default.
you can use export only
export const AppRoute = createAppContainer(DrawerNavigatorExample);
to import that
import { AppRoute } from 'App.js';
I think you can export default your class like this:
import React, { Component } from 'react';
import { View, Image, TouchableOpacity } from 'react-native';
import {
createDrawerNavigator,
createStackNavigator,
createAppContainer,
} from 'react-navigation';
import Screen1 from './pages/Screen1';
import Screen2 from './pages/Screen2';
import Screen3 from './pages/Screen3';
class NavigationDrawerStructure extends Component {
toggleDrawer = () => {
this.props.navigationProps.toggleDrawer();
};
render() {
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={this.toggleDrawer.bind(this)}>
{/*Donute Button Image */}
<Image
source={require('./image/drawer.png')}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
}
const FirstActivity_StackNavigator = createStackNavigator({
First: {
screen: Screen1,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 1',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
const Screen2_StackNavigator = createStackNavigator({
Second: {
screen: Screen2,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 2',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
const Screen3_StackNavigator = createStackNavigator({
Third: {
screen: Screen3,
navigationOptions: ({ navigation }) => ({
title: 'Demo Screen 3',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff',
}),
},
});
export const DrawerNavigatorExample = createAppContainer({
Screen1: {
//Title
screen: FirstActivity_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 1',
},
},
Screen2: {
//Title
screen: Screen2_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 2',
},
},
Screen3: {
//Title
screen: Screen3_StackNavigator,
navigationOptions: {
drawerLabel: 'Demo Screen 3',
},
},
});
export default new NavigationDrawerStructure();
Than, you can import like this:
import { DrawerNavigatorExample }, NavigationDrawerStructure from './App.js';
I have 2 screens;
Login screen
Main screen with 2 tabs in it. (createbottomnavigation)
I want to acces my 3rd screen from Main screen, but I got an error: "undefined is not an object..."
Here is my routes in app.js:
const Routes = createStackNavigator(
{
Login: {
screen: Login,
navigationOptions: ({ navigation }) => ({
header: null,
}),
},
Main: {
screen: MainScreenRoutes,
navigationOptions: ({navigation}) => ({
header: null,
}),
},
MyProfil: {
screen: MyProfile,
}
},
{
initialRouteName: 'Login',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
I can not access MyProfil from "Main" screen where I had my tabs.
Main profile router:
let headerDefaultNavigationConfig = {
header: props => <CustomHeader {...props} />,
...HeaderStyles
};
const Tab1 = createStackNavigator(
{
Domov: {
screen: HomeScreen,
navigationOptions: {
},
},
/*MyProfil: {
screen: MyProfil,
}*/
},
{
navigationOptions: {
...headerDefaultNavigationConfig
}
}
);
const Tab2 = createStackNavigator(
{
Dnevnik: {
screen: Diary,
navigationOptions: {
headerTitle: "Tab2",
headerLeft: (
<Text>Ok</Text>
)
},
}
},
{
navigationOptions: {
...headerDefaultNavigationConfig
}
}
);
const bottomTabs = createBottomTabNavigator(
{
Domov: Tab1,
Dnevnik: Tab2,
},
{
initialRouteName: "Domov",
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Domov') {
//iconName = `home${focused ? '' : '-outline'}`;
iconName='home';
} else if (routeName === 'Dnevnik') {
//iconName = `ios-calendar${focused ? '' : '-outline'}`;
iconName='ios-calendar';
}
// if focused return view with line
if(focused) {
return (
<View style={styles.item}>
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
<View style={styles.line}></View>
</View>
);
} else {
return(
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
)
}
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: 'white',
showLabel: false,
inactiveTintColor: '#4C2601',
style: {
backgroundColor: '#033D51',
},
labelStyle: {
fontSize: 12,
lineHeight: 30,
},
},
swipeEnabled: true,
});
/*const All = createStackNavigator(
{
"Home":{
screen: bottomTabs,
navigationOptions: {
header: null,
},
},
"MyProfil":{screen: MyProfil},
},
{
initialRouteName: 'Home',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
*/
export default bottomTabs;
This is my code to change screen;
const { navigate } = this.props.navigation;
navigate('MyProfil');
I adding image of screen, this work in part of screen.
The Contacts screen need to be main page and not screen1 but its didn't work if i replace between them.
I adding the code, in 'LogedInNavigator' have there TabNavigator and DrawerNavigator - the 'Contants' page initializing from TabNavigator and part two - Screen1 with the side menu it's from DrawerNavigator - maybe it's doing the problem?
LogedInNavigator.js
import.......
styles......
const LoggedInNavigator = TabNavigator(
{
Contacts: {screen: ContactScreen,},
Chat: {screen: ChatScreen,},
Dashbaord: {screen: DashbaordScreen,},
Profile: {screen: ProfileScreen,},
Search: {screen: SearchScreen,},
},
{
initialRouteName: "Contacts",
tabBarPosition: "bottom",
tabBarOptions: {
showIcon: true,
activeTintColor: 'white',
}
}
);
export default () => <LoggedInNavigator onNavigationStateChange={null} />
export const Drawer = DrawerNavigator ({
Home:{
screen: Screen1,
navigationOptions: {
drawer:{
label: 'Home',
},
}
},
Camera: {
screen: Screen2,
navigationOptions: {
drawer:{
label: 'Camera',
},
}
},
})
Contants.js
class Contacts extends Component {
componentDidMount() {
// TBD loggedin should come from login process and removed from here
const { loggedIn, getContacts } = this.props;
loggedIn(1);
getContacts();
}
render() {
const Router = createRouter( () => ({})); //IDAN
const { navigation, avatar, contacts } = this.props;
return (
<NavigationProvider router={Router}>
<View style={{flex:1}}>
<ContactView
navigation={navigation}
avatar={avatar}
contacts={contacts}
/>
<Drawer />
</View>
</NavigationProvider>
);
}
}
const mapStateToProps = (state) => {
return (
{
avatar: state.user.user.avatar,
contacts: state.contacts.contacts,
}
);
};
export default connect(mapStateToProps, { loggedIn, getContacts })(Contacts);
Help me please..
After a while, i want to answer on my own question (with react-navigation v2)
everything inside <RootNavigator/>
const RootNavigator= createDrawerNavigator({ Tabs }, {
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width * .75,
})
SideMenu:
class SideMenu extends Component {
render() {
return ( //...your side menu view )
}
}
Tab:
export default createBottomTabNavigator({
Menu: {
screen: HomeStack,
navigationOptions: {
title: 'תפריט',
tabBarIcon: ({ focused, tintColor }) => {
return <Icon name={'home'} size={20} color={tintColor} />;
},
}
},
Dashboard: {
screen: DashboardStack,
navigationOptions: {
title: 'בית',
tabBarOnPress: ({ navigation, defaultHandler }) => handleTabPress(navigation, defaultHandler),
tabBarIcon: ({ focused, tintColor }) => {
return <Icon name={'dashboard'} size={20} color={'green'} />;
},
}
},
QuickView: {
screen: QuickNav,
navigationOptions: {
title: 'מבט מהיר',
tabBarIcon: ({ focused, tintColor }) => {
return <Icon name={'short-list'} size={20} color={tintColor} />;
},
},
},
Chat: {
screen: Chat,
navigationOptions: {
title: "צ'אט",
tabBarIcon: ({ focused, tintColor }) => {
return <Icon name={'chat'} size={20} color={tintColor} />;
},
},
},
},
{
initialRouteName: 'Dashboard',
tabBarOptions: {
activeTintColor: 'green',
labelStyle: {
fontSize: 16,
marginBottom: 3,
},
},
},
)
For v5 onwards you can use drawer style
import deviceInfoModule from 'react-native-device-info';
<Drawer.Navigator
drawerStyle={{
width: deviceInfoModule.isTablet()
? Dimensions.get('window').width * 0.55
: Dimensions.get('window').width * 0.7,
}}
You can set the drawer width using Dimensions width. See the docs here
https://reactnavigation.org/docs/navigators/drawer
import { Dimensions } from 'react-native';
...
const { width } = Dimensions.get('screen');
...
export const Drawer = DrawerNavigator (
{
Home:{
screen: Screen1,
navigationOptions: {
drawer:{
label: 'Home',
},
}
},
Camera: {
screen: Screen2,
navigationOptions: {
drawer:{
label: 'Camera',
},
}
},
},
{
drawerWidth: width
});
In react-navigation version 6, you can use the drawerStyle in the screenOptions prop in the Drawer.Navigator component to change the width and add styles. This applies the applied style to all screens in the navigator.
<Drawer.Navigator
screenOptions: {{
drawerStyle: {
width: 240
}
}}
>
If you want the drawer to cover the entire screen, then import Dimensions from the react-native library and use Dimensions.get('window').width
import { Dimensions } from 'react-native'
<Drawer.Navigator
screenOptions: {{
drawerStyle: {
width: Dimensions.get('window').width
}
}}
>
Refer to react-navigation drawer for more.