Upgrading from 5.x
React Navigation 6 keeps the same API as React Navigation 5, however there are some breaking changes to make the API more consistent, more flexible and less confusing.
This guide lists all the changes that you need to keep in mind when upgrading.
General changes
These following changes are in the core library. You'll need to address this changes when upgrading the @react-navigation/native
package.
Older versions of some libraries are no longer supported
React Navigation now requires newer versions of following libraries:
react-native-safe-area-context
>= 3.0.0react-native-screens
>= 2.15.0react-native-tab-view
>= 3.0.0react-native
>= 0.63.0expo
- 40+ (if you use Expo)
Params are now overwritten on navigation instead if merging
This is probably one of the biggest changes. When navigating to an existing screen, we've merged the new params with the existing params since the first version of React Navigation.
For example, let's say there's an existing Post
screen with the following params:
And you navigate to it with navigation.navigate('Post', { postTitle: 'An okay post' })
, it'll have the following params:
While this merging behavior might be useful in some scenarios, it can be problematic in other cases. We also have had many bug reports where users were confused with this behavior.
So we're changing the default behavior in React Navigation 6 so that the params aren't merged by default anymore, and new params overwrite all existing params.
While the default has changed, it's still possible to merge params if you need it. To get the previous behavior, you can pass an object to navigate
with merge: true
and it'll merge the params:
dangerously
from dangerouslyGetParent
and dangerouslyGetState
Dropped The dangerouslyGetParent
and dangerouslyGetState
methods on the navigation
prop are useful in many scenarios, and sometimes necessary. So we dropped the dangerously
prefix to make it clear than it's safe to use. Now you can use navigation.getParent()
and navigation.getState()
.
state
property on the route
prop
No more The route
prop passed to components often contained a state
property which held state of the child navigator. While it wasn't meant to be public and we recommended against using it in the docs, we've seen a lot of people use this property.
It's problematic to use the property since it's not guaranteed to exist before navigation happens in the child navigator. This can cause subtle bugs in your app which you might not notice during development. So we have started warning on using this property in React Navigation 5 and removed this property entirely in React Navigation 6 prevent its usage.
If you need to have some configuration based on which screen is focused in child navigator, you can still do it using the getFocusedRouteNameFromRoute utility.
path
property on the route
prop
New The route
prop will now contain a path
property when opened from a deep link. You can use this property to further customize the content of the screen, e.g. load the page in a WebView
. See Handling unmatched routes or 404 for more details.
Linking configuration is now stricter
Older versions of React Navigation 5 had a slightly different configuration format for linking. The old config allowed a key value pair in the object regardless of nesting of navigators:
Let's say, your Feed
and Profile
screens are nested inside Home
. Even if you don't have such a nesting with the above configuration, as long as the URL was /home/profile
, it would work. Furthermore, it would also treat path segments and route names the same, which means that you could deep link to a screen that's not specified in the configuration. For example, if you have a Albums
screen inside Home
, the deep link /home/Albums
would navigate to that screen. While that may be desirable in some cases, there's no way to prevent access to specific screens. This approach also makes it impossible to have something like a 404 screen since any route name is a valid path.
Newer versions of React Navigation 5 supported a different config format which is stricter in this regard:
- The shape of the config must match the shape of the nesting in the navigation structure
- Only screens defined in the config will be eligible for deep linking
So, you'd refactor the above config to the following format:
Here, there's a new screens
property to the configuration object, and the Feed
and Profile
configs are now nested under Home
to match the navigation structure.
While the old format still worked in React Navigation 5, React Navigation 6 drops support for the old format entirely in favor of the new stricter format.
useLinking
hook
Dropped The useLinking
hook was the initial implementation of deep linking in React Navigation 5. Later, we moved to the linking
prop to make it easier to handle deep links. The hook was still exported not to break existing apps using it.
In 6.x, we finally removed the hook in favor of the linking
prop. If you're still using the useLinking
hook, it should be pretty straightforward to migrate as you just need to pass the config to linking
prop instead.
See configuring links for more details on configuring deep links.
Stack Navigator
Thee following changes are in the @react-navigation/stack
package.
New default animations for modal screens
To match the default behavior of iOS, now mode="modal"
shows the new presentation style modal introduced in iOS 13. It also adjusts things like status bar height in the header automatically that you had to do manually before.
Previously Android didn't have any special animation for modals. But now there's a slide from bottom animation instead of the default animation.
If you don't want to use the new animations, you can change it to your liking using the animation related options
headerMode="none"
is removed in favor of headerShown: false
Previously, you could pass headerMode="none"
prop to hide the header in a stack navigator. However, there is also a headerShown
option which can be used to hide or show the header, and it supports configuration per screen.
So instead of having 2 ways to do very similar things, we have removed headerMode="none"
in favor of headerShown: false
. To get the old behavior, specify headerShown: false
in screenOptions
:
`headerMode is moved to options
Previously, headerMode
was a prop on the navigator, but now it needs to be specified in screen's options
instead. To keep previous behavior, you can specify it in screenOptions
:
The headerMode
option supports 2 values: screen
and float
.
Custom header now uses 'headerMode: screen' by default
Previously it was necessary to specify headerMode='screen'
or a custom animation manually when using a custom header. Even though this was mentioned in the docs, it has been tripped up many people.
But now specifying a custom header automatically sets headerMode
to screen
, so it doesn't need anything more. This is now possible because headerMode
is no longer a prop for the navigator, so it can be configured per screen where a custom header is specified.
Props passed to custom header are streamlined
Previously, the stack header accepted scene and previous scene which contained things such as descriptor
, navigation
prop, progress
etc. The props are now simplified to following. See header docs for the list.
If you have a custom header, you may need to adjust it to use the new props.
Header now uses flexbox
The header elements were rendered using absolute positioning which didn't work well in certain situations. We now use flexbox for header elements which should work better. If you have code which relied on the absolute positioning, you'll need to change it.
gestureResponseDistance
option is now a number instead of an object
The Previously, the gestureResponseDistance
option took an object with horizontal
and vertical
properties. Now it takes a number which will be used as the horizontal or vertical value based on the gestureDirection
option.
Some exports are now moved to the element library
The following exports now live in the elements library since they are no longer specific to the stack navigator:
Assets
HeaderTitle
HeaderBackButton
HeaderBackground
HeaderHeightContext
useHeaderHeight
See below for more details on installing the elements library.
Bottom Tab Navigator
The following changes are in the @react-navigation/bottom-tabs
package.
A header is shown by default in tab screens
Tab screens now show a header by default similar to screens in a stack navigator. This avoid the need for nesting a stack navigator in each screen just for a header. See its options to see all header related options.
To keep the previous behavior, you can use headerShown: false
in screenOptions
.
The tab bar now shows a question mark when an icon isn't passed instead of empty area
Previously the tab bar in bottom tabs showed an empty area when no icon was specified. Now it shows a question mark to make it more obvious that the icon is missing.
tabBarOptions
prop is now more flexible by moving to options
for bottom tabs
The The tabBarOptions
prop was removed and the options from there were moved to screen's options
instead. This makes them configurable on a per screen basis.
The list of the options and their new name are follows:
keyboardHidesTabBar
->tabBarHideOnKeyboard
activeTintColor
->tabBarActiveTintColor
inactiveTintColor
->tabBarInactiveTintColor
activeBackgroundColor
->tabBarActiveBackgroundColor
inactiveBackgroundColor
->tabBarInactiveBackgroundColor
allowFontScaling
->tabBarAllowFontScaling
adaptive
->tabBarAdaptive
showLabel
->tabBarShowLabel
labelPosition
->tabBarLabelPosition
labelStyle
->tabBarLabelStyle
iconStyle
->tabBarIconStyle
tabStyle
->tabBarItemStyle
style
->tabBarStyle
To keep the same behavior as before, you can specify these in screenOptions
.
tabBarVisible
option is no longer present
The Since the the tab bar now supports a tabBarStyle
option, we have removed the tabBarVisible
option. You can achieve the same behavior by specifying tabBarStyle: { display: 'none' }
in options
.
lazy
prop is moved to lazy
option for per-screen configuration for bottom tabs
The The lazy
prop now can be configured per screen instead of for the whole navigator. So it's moved to options
from props. To keep previous behavior, you can specify it in screenOptions
to apply it to all screens.
backBehavior
is now firstRoute
for bottom tabs
The default value for Returning to first route after pressing back seems more common in apps. To match this behavior, drawer now uses firstRoute
for the backBehavior
prop. To preserve old behavior, you can pass backBehavior="history"
prop to the bottom tab navigator.
Material Top Tab Navigator
The following changes are in the @react-navigation/material-top-tabs
package.
ViewPager
instead of Reanimated and Gesture Handler
It now uses The react-native-tab-view
dependency is upgraded to the latest version (3.x) which now uses ViewPager
instead of Reanimated and Gesture Handler. This will provide a native UX and also improve the performance.
See release notes for react-native-tab-view
for more details.
tabBarOptions
prop is now more flexible by moving to options
for material top tabs
The Similar to bottom tabs, the tabBarOptions
prop was removed and the options from there were moved to screen's options
instead.
The list of the options and their new name are follows:
activeTintColor
->tabBarActiveTintColor
inactiveTintColor
->tabBarInactiveTintColor
pressColor
->tabBarPressColor
pressOpacity
->tabBarPressOpacity
showLabel
->tabBarShowLabel
showIcon
->tabBarShowIcon
allowFontScaling
->tabBarAllowFontScaling
bounces
->tabBarBounces
scrollEnabled
->tabBarScrollEnabled
iconStyle
->tabBarIconStyle
labelStyle
->tabBarLabelStyle
tabStyle
->tabBarItemStyle
indicatorStyle
->tabBarIndicatorStyle
indicatorContainerStyle
->tabBarIndicatorContainerStyle
contentContainerStyle
->tabBarContentContainerStyle
style
->tabBarStyle
To keep the same behavior as before, you can specify these in screenOptions
.
lazy
prop is moved to lazy
option for per-screen configuration for material top tabs
The Similar to bottom tabs, the lazy
prop is now moved to options
for material top tabs.
backBehavior
is now firstRoute
for material top tabs tabs
The default value for Similar to bottom tabs, material top tabs now uses firstRoute
for the backBehavior
prop as well.
Material Bottom Tab Navigator
The following changes are in the @react-navigation/material-bottom-tabs
package.
backBehavior
is now firstRoute
for material bottom tabs
The default value for Similar to bottom tabs, material bottom tabs now uses firstRoute
for the backBehavior
prop as well.
Drawer Navigator
The following changes are in the @react-navigation/drawer
package.
A header is shown by default in drawer screens
Tab screens now show a header by default similar to screens in a stack navigator and bottom tab navigator. See its options to see all header related options.
To keep the previous behavior, you can use headerShown: false
in screenOptions
.
Slide animation is now default on iOS
Drawer now uses a slide animation by default on iOS. To keep the previous behavior, you can specify drawerType="front"
in screenOptions
.
Drawer status is now a string instead of a boolean
Previously, the status of drawer was a boolean
(true
| false
) to signify the open and closed states. It's now a string with the values open
and closed
. This will let us implement more types of status in future.
To match this change, the following exports have been renamed as well:
getIsDrawerOpenFromState
->getDrawerStatusFromState
useIsDrawerOpen
->useDrawerStatus
drawerOpen
and drawerClose
events
Drawer no longer emits The drawerOpen
and drawerClose
events are now removed because same information can be achieved from the following helpers:
useDrawerStatus
hookgetDrawerStatusFromState
helper (e.g. -getDrawerStatusFromState(navigation.getState())
)
drawerContentOptions
prop is now more flexible by moving to options
for drawer
The The drawerContentOptions
prop was removed and the options from there were moved to screen's options
instead. This makes them configurable on a per screen basis.
The following options have been moved without renaming:
drawerPosition
drawerType
keyboardDismissMode
overlayColor
gestureHandlerProps
The following options have been moved and renamed:
hideStatusBar
->drawerHideStatusBarOnOpen
statusBarAnimation
->drawerStatusBarAnimation
edgeWidth
->swipeEdgeWidth
minSwipeDistance
->swipeMinDistance
To keep the same behavior as before, you can specify these in screenOptions
.
lazy
prop is moved to lazy
option for per-screen configuration for drawer
The Similar to bottom tabs, the lazy
prop is now moved to options
for drawer.
backBehavior
is now firstRoute
for drawer
The default value for Similar to bottom tabs, drawer now uses firstRoute
for the backBehavior
prop as well.
Elements Library
We have a new package which contains various UI elements related to navigation, such as a Header
component. This means that we can now use these components in all navigators. You can also install the library to import components such as Header
to use in any navigator:
Now you can import items from there:
See the Elements Library page for more details on what's available in the library.