Integrating React Native Navigators

Software Developer
Talk with our tech expert & find initial solutions the challenge, that is currently crucial for your business

React Navigation has become a standard in navigating between screens in the React Native. There are just four basic navigators, with an option to create a custom one, but the magic happens when you combine them in the right way.

Table of contents:

react native navigation

Stack navigator

  • transitions between screens
  • navigation history on stack
  • built-in header

Bottom tab navigator

  • no navigation history
  • buggy API for returning active tab
  • highly customizable bottom tab

Switch navigator

  • no additional UI
  • automatic screen unmount on leave
  • returns to initial screen on back button press (no navigation history)

We’ll skip the Drawer Navigator to use the Tab Navigator Instead.

First navigator

SwitchNavigator will be the type of the root navigator. Add Splash screen which automatically redirects to the Launch screen and also write SignUpName and SignUpVerifyEmail with simple buttons that change screens.

const PrimaryNav = createSwitchNavigator(
  {
    Splash: SplashScreen,
    Launch: LaunchScreen,
    SignUpName: SignUpNameScreen,
    SignUpVerifyEmail: SignUpVerifyEmailScreen
  },
  {
    initialRouteName: 'Splash',
    backBehavior: 'initialRoute'
  }
)

export default PrimaryNav

react native navigator

Tab navigation

Inside SwitchNavigator, include TabNav with its 3 screens. It’s important to do it directly here and not to render it like <TabNav /> to keep navigation state in one place and avoid denying access to the screens in incorrectly rendered navigation from the PrimaryNav screens.

const TabNav = createBottomTabNavigator({
  Home: HomeScreen,
  Notifications: NotificationsScreen,
  Info: InfoScreen
})

const PrimaryNav = createSwitchNavigator(
  {
    MainNav: TabNav,
    Splash: SplashScreen,
    Launch: LaunchScreen,
    SignUpName: SignUpNameScreen,
    SignUpVerifyEmail: SignUpVerifyEmailScreen
  },
  ...

navigator react native

Nested stack navigator

Next, add separate Stack Navigators for each tab. Because it includes a header by default, and we already built one, create invisibleHeader object to unpack it in the config.

const invisibleHeader = {
  headerMode: 'none',
  navigationOptions: {
    headerVisible: false
  }
}

Stack navigators:

const HomeScreenNav = createStackNavigator(
  {
    Home: HomeScreen
  },
  {
    ...invisibleHeader,
    initialRouteName: 'Home'
  }
)

const NotificationsScreenNav = createStackNavigator(
  {
    Notifications: NotificationsScreen,
    Notification: NotificationScreen
  },
  {
    ...invisibleHeader,
    initialRouteName: 'Notifications'
  }
)

const InfoScreenNav = createStackNavigator(
  {
    Info: InfoScreen
  },
  {
    ...invisibleHeader,
    initialRouteName: 'Info'
  }
)

And modifiy the PrimaryNav to replace screens with new navigators

const PrimaryNav = createSwitchNavigator(
  {
    MainNav: TabNav,
    Splash: SplashScreen,
    Launch: LaunchScreen,
    SignUpName: SignUpNameScreen,
    SignUpVerifyEmail: SignUpVerifyEmailScreen
  },
  ...

react native navigators

Hide tab bar when going deep

Change bottom Tab config to hide the TabBar when switching away from the initial screen of each Stack Navigator.

for (let nav of [HomeScreenNav, NotificationsScreenNav, InfoScreenNav]) {
  nav.navigationOptions = ({ navigation }) => ({
    tabBarVisible: navigation.state.index <= 0
  })
}

Common screens in stack

We want to have access to some common screens in multiple places, without compromising the history integrity. The idea is to always keep navigators in a straight tree to prevent switching up and down the tree between navigators (branches) when we need to access common screens (actually any given screen). To do so, we simply duplicate common screens in each Stack Navigator. We keep it in a separate object:

const commonScreens = { Settings: SettingsScreen }

Next, add prefixes to each common screen, depending on the Stack Navigator initial screen name. If you are lazy like me, you can use ready-made frunctions from Ramda and Ramda-adjunct (my go-to utils libraries, like lodash but fully functional and never mutating input):

import * as R from 'ramda'
import { renameKeysWith } from 'ramda-adjunct'

const generateCommonScreens = prefix =>
  renameKeysWith(R.concat(prefix), commonScreens)

Or just write your own. It’s simply adding a prefix to each object key.

Then also unpack it to each Stack Navigator like so:

const HomeScreenNav = createStackNavigator(
  {
    ...generateCommonScreens('Home'),
    Home: HomeScreen
  },
  ...

After it navigate to whatever common screen we want and pass according screen name depending on what tab it has to navigate from, e.g. HomeSettings and InfoSettings.

integrating react native navigators

Custom back button behavior

There is no reliable built-in way to get the current screen in TabNavigator. To customize the back button behavior, create a custom container to wrap screens with.

import React, { Component } from 'react'
import { withNavigation } from 'react-navigation'
import { BackHandler } from 'react-native'

class HandleBack extends Component {
  constructor(props) {
    super(props)
    const { navigation } = this.props
    this.state = {
      active: false
    }
    this.didFocus = navigation.addListener('didFocus', payload => {
      this.setState({ active: true })
    })
    this.didBlur = navigation.addListener('didBlur', payload => {
      this.setState({ active: false })
    })
    BackHandler.addEventListener('hardwareBackPress', this.onBack)
  }

  componentWillUnmount() {
    this.didFocus.remove()
    this.didBlur.remove()
    BackHandler.removeEventListener('hardwareBackPress', this.onBack)
  }

  onBack = () => {
    if (this.state.active) {
      BackHandler.exitApp()
      return true
    }
    return false
  }

  render() {
    return this.props.children
  }
}

export default withNavigation(HandleBack)

We have to manually save whether the current tab is active or not. Explicit cleanup of event listeners is also a good practice. Lastly, wrap the Home Screen with this component in the render function.

navigators react native

Would you like to talk with our experts about technology solutions for your business?

5/5 - (1 vote)
Software Developer
Talk with our tech expert & find initial solutions the challenge, that is currently crucial for your business
Share on facebook
Share on linkedin

Share the article

inspeerity_kamil

Software consultation

Fill in the form

The more information you can provide us, the better understanding we have of who will be perfect match for your chat.

Get a reply

Get a reply in only 2 hours and schedule your 15min call.

Receive recommendations

Receive an e-mail with recommendations crafted to your need & business.

Share on facebook
Share on linkedin

We use cookies to ensure you get the best experience on our website.