For navigating between screens in React Native, React Navigation has become an important and essential standard. There are only four basic navigators, with the option to create a custom one, but magic happens when you combine them properly.
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
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
},
...
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
},
...
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
.
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.
Would you like to talk with our experts about technology solutions for your business?
Q: What is React Navigation?
React Navigation is a library for navigating between screens in a React Native app. It has four basic navigators, with the option to create a custom one, and allows for combinations of navigators to create a customized navigation experience.
Q: What are the different types of navigators in React Navigation?
The four basic navigators in React Navigation are Stack Navigator, Tab Navigator, Switch Navigator, and Drawer Navigator.
Q: How can I create nested Stack Navigators?
To create nested Stack Navigators, include a separate Stack Navigator for each tab within the Tab Navigator. Make sure to set the header to ‘none’ and set the initialRouteName to the desired screen.
<Source: https://inspeerity-com.translate.goog/blog/integrating-react-native-navigators?_x_tr_sl=auto&_x_tr_tl=vi&_x_tr_hl=en-US>
No comments:
Post a Comment