React native change screen from bottom navigation - javascript

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');

Related

Switch Navigator and Tab Navigator Conflict

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,
});

React native bottom navigation in main screen

I have 2 screens.
First one is Login screen(without header) where I have "createStackNavigation"
and second one is Main screen where I would like to have bottom navigation(2 tabs) with Header in each of these two tabs.
I did bottom navigation but custom header does not work at all...It's only basic header. Can anyone have some basic example of this? Or can help me with tutorial?
My code in app.js:
const RootStack = createStackNavigator(
{
Home: {
screen: Login,
navigationOptions: ({ navigation }) => ({
header: null,
}),
},
Main: MainScreen,
},
{
initialRouteName: 'Home',
headerMode: 'screen',
}
);
My code in "Main" screen:
export default createBottomTabNavigator(
{
Domov: {
screen: HomeScreen,
},
Dnevnik: Diary,
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Domov') {
iconName='home';
} else if (routeName === 'Dnevnik') {
iconName='ios-calendar';
}
return (
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
);
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: 'white',
showLabel: false,
inactiveTintColor: '#4C2601',
style: {
backgroundColor: '#033D51',
},
},
});
Thank you
Add header: null in your navigationOptions in Main screen. You'll be able to add your custom header.

StackNavigator in TabNavigator in StackNavigator, TabNavigator switches to wrong tab

I'm currently facing an issue where my TabNavigator which is nested inside a StackNavigator is not opening in the initialRouteName that I define.
It's easiest to see this with an example so here we go:
Outermost (StackNavigator)
const RootStackNavigator = StackNavigator(
{
Main: {
screen: MainTabNavigator,
},
Login: {
screen: LoginScreen,
},
Splash: {
screen: SplashScreen
}
},
{
initialRouteName: 'Splash',
headerMode: 'float',
}
);
export default class RootNavigator extends React.Component {
componentDidMount() {
this._notificationSubscription = this._registerForPushNotifications();
}
componentWillUnmount() {
this._notificationSubscription && this._notificationSubscription.remove();
}
render() {
return (
<RootStackNavigator />
);
}
}
MainTabNavigator (TabNavigator):
const HomeStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'HomeScreen',
headerMode: 'none',
}
);
const BStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'BScreen',
headerMode: 'none',
}
);
const CNavigator = StackNavigator(
{
//Lots of screens
},
{
initialRouteName: 'CScreen',
headerMode: 'none',
}
);
const DStackNavigator = StackNavigator(
{
//Lots of screens.
},
{
initialRouteName: 'DScreen',
headerMode: 'none',
}
);
const EStackNavigator = StackNavigator(
{
//Lots of screens
},
{
initialRouteName: 'EScreen',
headerMode: 'none',
}
);
export default TabNavigator(
//Adds elements to the navigator at the bottom.
{
Home: {
screen: HomeStackNavigator
},
B: {
screen: BStackNavigator,
},
C: {
screen: CStackNavigator,
},
D: {
screen: DStackNavigator,
},
E: {
screen: EStackNavigator,
}
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
let iconName;
switch (routeName) {
//define icons.
}
return (
<Ionicons
name={iconName}
size={24}
style={{ marginBottom: -3 }}
color={focused ? Colors.tabIconSelected : Colors.tabIconDefault}
/>
);
},
}),
tabBarOptions: {
inactiveBackgroundColor: '#4d5a8b',
activeBackgroundColor: '#4d5a8b',
showLabel: false,
initialRouteName: 'Home'
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false
}
);
What I'm expecting is for the app to initially go to the splash screen. Check if the user is signed in, yes they are, then go to the MainTabNavigator's initialRouteName but what actually happens is that it's initially loads in the Home tab, and then after about 2-3 seconds it flicks over to the D tab.
Note: One thing I have noticed is that I have some screens in multiple of the StackNavigators for the tabs, for example you can navigate to ScreenX from the BStackNavigator and the CStackNavigator.
Has anyone experienced this before and have a way of getting around it?
I'd really appreciate any help.
Thanks!
I think it is because the initialRouteName parameter is at the wrong place.
Example:
export default TabNavigator(
//Adds elements to the navigator at the bottom.
{
Home: {
screen: HomeStackNavigator
},
B: {
screen: BStackNavigator,
},
C: {
screen: CStackNavigator,
},
D: {
screen: DStackNavigator,
},
E: {
screen: EStackNavigator,
}
},
{
initialRouteName: 'Home', // SHOULD BE HERE
navigationOptions: ({ navigation }) => ({
...
}),
tabBarOptions: {
inactiveBackgroundColor: '#4d5a8b',
activeBackgroundColor: '#4d5a8b',
showLabel: false,
//initialRouteName: 'Home', SHOULD NOT BE HERE
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false
}
);
Doc:
TabNavigator API

How to reset from drawer navigator to tab navigator in react native?

This is my current navigation
const MainNavigator = TabNavigator(
{
SignIn: {
screen: SignInScreen,
},
Home: {
screen: SubNavigator,
}
},
{
navigationOptions: {
tabBarVisible: false,
swipeEnabled: false
},
initialRouteName: 'SignIn',
lazy: true
}
);
const SubNavigator = DrawerNavigator(
{
Page1: {
screen: StackNavigator(
{
pageOne: {
screen: ScreenOne,
navigationOptions: ({ navigation }) => ({
title: 'One',
headerLeft: (
<TouchableOpacity onPress={() => navigation.navigate('DrawerOpen')}>
<IOSIcon name="ios-menu" size={30} />
</TouchableOpacity>
),
headerStyle: { paddingRight: 10, paddingLeft: 10 },
})
},
pageTwo: { screen: ScreenTwo },
camera: {
screen: CameraScreen,
navigationOptions: {
title: 'Camera'
}
},
qrscanner: {
screen: QRScanner,
navigationOptions: {
title: 'QR Scanner'
}
},
},
)
},
Profile: {
screen: ProfileScreen, // log out from here
},
},
{
contentComponent: SideMenu,
initialRouteName: 'Driver',
contentOptions: {
activeTintColor: '#e91e63'
}
}
);
I want to log out from Profile and reset it to SignIn. It is triggered by onPress.
Inside code for Profile I put function and render a text like this
/*.......*/
navigateToReset(route) {
const navigateReset = NavigationActions.reset({
index: 0, key: null, actions: [NavigationActions.navigate({ routeName: route })],
});
this.props.navigation.dispatch(navigateReset);
}
onButtonPressSignOut = () => {
this.navigateToReset('SignIn');
}
/*....*/
render () {
return(
<View>
<Text onPress={this.onButtonPressSignOut}>
Sign Out
</Text>
</View>
);
}
But this gave me error:
Error: There is no route defined for key SignIn.
Must be one of: 'pageOne', 'pageTwo', 'camera', 'qrscanner'
I have searched online and found several issue like this.
This is some of the issue I found : Issue1, Issue2 but it does not work for me.
Did I miss something in the above code?
Thank you for your help and suggestion.

Side menu not covering all screen (DrawerNavigator - React Native)

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.

Categories