1
votes

I'm trying to have one of the tab bar items open as modal when clicked, I'm currently using expo. I've read this: How do i make a TabNavigator button push a modal screen with React Navigation. However, I'm still learning React Native and I'm honestly not sure how to use this using expo navigation. Currently, I have created a stack navigator using "createStackNavigator" for each of the screens. And lastly, I have exported a bottom tab navigator including all of the stacks:

export default createBottomTabNavigator({ Tab1Stack, Tab2Stack, Tab3Stack, Tab4Stack });

I need Tab4 to open as a modal. Can someone people help me with this? Thank you in advance!!

1

1 Answers

4
votes

Note this was built for "react-navigation": "3.3.0" so your mileage my vary for more recent versions of Expo and react-navigation.

To make a modal appear when you tap on the last tab in a TabNavigator requires you to nest your TabNavigator inside a StackNavigator.

So we could set up something like this:

#App.js

A simple App.js.

import React from 'react';
import AppContainer from './MainNavigation';
export default class App extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
    };
  }

  render () {
    return (
      <AppContainer />
    );
  }
}

#MainNavigation.js

This file contains two navigators. A TabNavigator and a StackNavigator. The TabNavigator is nested inside the StackNavigator.

To be able to show the ModalScreen we have to override the tabBarOnPress function inside the defaultNavigationOptions which is inside the config for the TabNavigator.

We need to check the navigation.state.key to see where we are navigating too. If we are going to Tab3 we can intercept the call and navigate to the ModalScreen instead. Otherwise we use the defaultHandler and go to the tab that was tapped.

import Screen1 from './Screen1';
import Screen2 from './Screen2';
import Screen3 from './Screen3';
import ModalScreen from './ModalScreen';
import { createBottomTabNavigator, createAppContainer, createStackNavigator } from 'react-navigation';

const screens = {
  Tab1: {
    screen: Screen1
  },
  Tab2: {
    screen: Screen2
  },
  Tab3: {
    screen: Screen3
  }
};

const config = {
  headerMode: 'none',
  initialRouteName: 'Tab1',
  defaultNavigationOptions: {
    tabBarOnPress: (data) => {
      // this is where the magic happens
      const { navigation, defaultHandler } = data;
      // we check to see if the navigation key is going to be on Tab3
      if (navigation.state.key === 'Tab3') {
        // if it is we show the ModalScreen by navigating to it
        navigation.navigate('ModalScreen');
      } else {
        // otherwise we call the defaultHandler and navigate to the tab we pressed
        defaultHandler(navigation.state.key);
      }
    }
  }
};

const TabNavigator = createBottomTabNavigator(screens, config);

const stackScreens = {
  Tabs: {
    screen: TabNavigator
  },
  ModalScreen: {
    screen: ModalScreen
  }
};

//we need to set the mode to be modal
const stackConfig = {
  headerMode: 'none',
  initialRouteName: 'Tabs',
  mode: 'modal'
};

const MainNavigator = createStackNavigator(stackScreens, stackConfig);
export default createAppContainer(MainNavigator);

#Screen.js

A simple screen for each tab

import React from 'react';
import { View, StyleSheet, Text } from 'react-native';

export default class Screen extends React.Component {
  render () {
    return (
      <View style={styles.container}>
        <Text>Tab Screen</Text>
      </View>
    );
  }
}

#ModalScreen

This screen is the modal that will appear when the tab for the third screen is tapped. As it is part of the StackNavigator, defined above, it has access to the navigation prop. We set up a simple button that when pressed calls this.props.navigation.goBack() This will dismiss the modal.

import React from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';

export default class Screen extends React.Component {
  render () {
    return (
      <View style={styles.container}>
        <Text>Modal Screen</Text>
        <Button
          title={'close modal'}
          onPress={() => this.props.navigation.goBack()}
        />
      </View>
    );
  }
}

Here is a snack with it working, https://snack.expo.io/@andypandy/show-modal-on-tab-press, hopefully it will show you how to set it up.