Niklas Rosencrantz
Niklas Rosencrantz

Reputation: 26647

How to open a screen with React Native

I have created a tabbed view with three tabs based on RNE (React native elements demo app). enter image description hereI 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;

Upvotes: 3

Views: 1725

Answers (1)

Paras Watts
Paras Watts

Reputation: 2665

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.

Upvotes: 2

Related Questions