1

I'm completely new to React Native and I'm building an app for one of our clients.

I created a screen that shows a list of names that can be shown in either alphabetical or grouped by category. I used the react-native-tab-view component to make this work. Each of the two tabs renders their own respective screen component, ScreenMapAlpha (shows a FlatList) and ScreenMapCategory (shows a SectionList).

For each renderItem prop of these lists, I wanted to make each item clickable using a TouchableOpacity into like a details page, however I couldn't get the navigation.navigate() function to work as I keep getting this message:

TypeError: undefined is not an object (evaluating '_this3.props.navigation.navigate')

I've been reading up on the react-native-tab-view Github documentation but I couldn't find a way to pass the navigation object into both of the Alpha/Category screen components for it to work.

My code looks like this:

import * as React from 'react';
import { StyleSheet, Text, View, Dimensions } from 'react-native';
import ScreenMapAlpha from '../screens/map_alpha';
import ScreenMapCategory from '../screens/map_cat';
import { TabView, TabBar, SceneMap } from 'react-native-tab-view';

const initialLayout = { width: Dimensions.get('window').width };

const renderTabBar = props => (
  <TabBar
    {...props}
    indicatorStyle={{ backgroundColor: '#fff' }}
    style={{ backgroundColor: '#c00' }}
  />
);

export default function ScreenMap({ navigation }) {
    const [index, setIndex] = React.useState(0);
    const [routes] = React.useState([
        { key: 'first', title: 'Alphabetical' },
        { key: 'second', title: 'Category' }
    ]);

    const renderScene = SceneMap({
        first: ScreenMapAlpha,
        second: ScreenMapCategory
    });

    return (
        <TabView
            navigationState={{index, routes}}
            renderScene={renderScene}
            onIndexChange={setIndex}
            renderTabBar={renderTabBar}
            initialLayout={initialLayout}
            navigation={navigation}
        />
    )  
}

map_alpha.js

import React, { useEffect, useState } from 'react';
import { StyleSheet, View, Text, FlatList, Image, TouchableOpacity } from 'react-native';
import TenantListAlpha from '../shared/tableTenantAlpha';

export default function ScreenMapAlpha({ navigation }) {       
    return (
        <View style={styles.container}>
            <TenantListAlpha navigation={navigation} />
        </View>
    )  
}

map_cat.js

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import TenantListCat from '../shared/tableTenantCat';

export default function ScreenMapCategory({ navigation }) {
    return (
        <View style={styles.container}>
            <TenantListCat navigation={navigation} />
        </View>
    )  
}   

I'm using a StackNavigator for this app:

mapstack.js

import { createStackNavigator, createTopTabNavigator } from 'react-navigation-stack';
import Map from '../screens/map.js';
import React from 'react';
import CommonHeader from '../shared/header';
import TenantDetail from '../screens/tenant_detail';

const screens = {
    Map: {
        screen: Map,
        navigationOptions: ({ navigation }) => {
            return {
                headerTitle: () => <CommonHeader navigation={navigation} title="Directory" />
            }
        }
    },
    TenantDetail: {
        screen: TenantDetail,
        navigationOptions: ({ navigation }) => {
            return {
                //headerTitle: () => <CommonHeader navigation={navigation} title="News" />
                headerTitle: () => <Text>Directory</Text>
            }
        }
    }
}

const MapStack = createStackNavigator(screens);

export default MapStack;

I couldn't for the life of me figure this out - how do I pass the navigation object from the parent screen to the two screens in the tabs for navigation.navigate() to work?

tg13
  • 35
  • 3
  • 11

2 Answers2

5

It doesn't look like you're actually using react navigation. I would implement it, then navigation prop is passed to all your screens, you'll also be able to use the useNavigation() hook.

https://github.com/satya164/react-native-tab-view#react-navigation

https://reactnavigation.org/docs/tab-based-navigation

Edit: I highly recommend implementing one of the react-navigation tab view wrappers, however you may be able to get your current code to work by properly passing the navigation prop.

From the github page you have in your question: https://github.com/satya164/react-native-tab-view#renderscene-required

If you need to pass additional props, use a custom renderScene function:

const renderScene = ({ route }) => {
  switch (route.key) {
    case 'first':
      return <FirstRoute foo={this.props.foo} />;
    case 'second':
      return <SecondRoute />;
    default:
      return null;
  }
};

Which in your case would look like:

const renderScene = ({ route }) => {
  switch (route.key) {
    case 'first':
      return <ScreenMapAlpha navigation={navigation} />;
    case 'second':
      return <ScreenMapCategory navigation={navigation} />;
    default:
      return null;
  }
};
GitGitBoom
  • 1,822
  • 4
  • 5
  • I'm using StackNavigator, sorry forgot to specify that. I added my stack code above. Honestly I'm having trouble understanding the documentation, I came from a PHP background and only learning react-native for a couple weeks now and everything's still new and confusing to me. I'll try to get the useNavigation() hook to work, fingers crossed! – tg13 Jul 30 '20 at 21:27
  • 1
    No worries, your probably running into trouble since the stack navigation your using is a version behind (version 4) and you may be reading docs for version 5. If you can: I would not use ```react-navigation-stack``` instead use ```@react-navigation/stack``` note the implementation is completely different. As for tabs: your trying to use the ```react-native-tab-view``` module directly, you need to use one of their wrappers like this one https://reactnavigation.org/docs/material-top-tab-navigator/ (also version 5) – GitGitBoom Jul 30 '20 at 21:38
  • 1
    Tab navigation in version 4: https://reactnavigation.org/docs/4.x/tab-based-navigation – GitGitBoom Jul 30 '20 at 21:39
  • The custom renderScene function did the trick! That's what I've been trying to do all this time, I needed to pass the navigation object to the two screens in the tab component, I just didn't know the correct syntax! The way functions are written in React/ES5 is an entirely new concept for me, so this has been a huge help. Thank you!! – tg13 Jul 31 '20 at 14:28
1

create a function in const.js

import React from 'react';
import { useNavigation } from '@react-navigation/native'; 

export const withNavigation = (Component: any) => {
  return (props: any) => {
    const navigation = useNavigation();

    return <Component navigation={navigation} {...props} />;
  };
};

import and use in your componant

import {
  withNavigation,
} from '../../helpers/functions';


export default  withNavigation(OrgWiseEvents)
Rajesh N
  • 6,198
  • 2
  • 47
  • 58