The documentation is now live at reactnavigation.org, and v1 lives here.
Significant breaking changes
The following changes are considered “significant” because they can’t be fixed by search and replace or something that is similarly mechanical.
navigate(routeName)
in StackNavigator is “less pushy”
In 1.x, navigate(routeName)
and push(routeName)
were very similar: every time you called navigate(routeName)
it would push a new route to the stack. Now navigate(routeName)
will first try to find an existing instance of the route and jump to that if it exists, otherwise it will push the route to the stack.
To update your app for this change you may need to change navigate
to push
in places where you would like to push a new route every time. Alternatively, you could consider using a key
: navigate({routeName: ‘MyRoute’, key: data.uniqueId, params: data})
. Read more about navigation with keys.
Read more about this in RFC 4 and commit 7a978b1.
push
now propagates between routers like navigate
Previously, push
only applied to the deepest active stack router. This meant that if you had Stack A > Stack B and Stack B fired push(‘MyRoute’)
, even if Stack B does not have a route with the name ’MyRoute’
and Stack A does, the screen would not be pushed. We made this change to accommodate for the “less pushy” navigate behavior.
When updating your app, you may want to double check where you use push
to ensure that this doesn’t impact the expected behavior of your app.
Read about this in RFC 4 and pull 3617.
Shallow navigation options
A common source of confusion for developers working with React Navigation has been around navigationOptions
resolution. For example, if you have a stack navigator with a header, and a drawer inside of that stack, then in some circumstances the title of the stack would change every time you change screens in the drawer. This is because the stack navigator would crawl into child navigators and pull navigationOptions
off of the deepest active screen. As of 2.0, this no longer happens: navigators will only look at their direct children for navigationOptions
.
Read more about the justification for this in RFC 5. Also see the new documentation page Navigation options resolution to learn more.
New API for creating navigators
It is now easier to create and maintain custom navigators. The new createNavigator
API fully decouples the navigation view from the router. Information about each screen is available on a single "descriptor", including the pre-computed child navigation prop, allowing you to focus on custom navigation views.
Custom navigators can now provide actions helpers for their screens. For example, the new drawer navigator now allows props.navigation.openDrawer()
within its screen components.
This does not impact most users - you won't need to make any changes for this unless you use custom navigators in your app. Read more about the changes in RFC 2. Also read the custom navigators documentation. You can also watch the "Creating a navigator" section in this talk to learn more.
Trivial breaking changes
The following changes are considered “trivial” because you will only need make straightforward and mechanical changes to update your app for them.
Drawer routes have been replaced with actions
Rather than opening a drawer with navigation.navigate(‘DrawerOpen’)
, you can now call navigation.openDrawer()
. Other methods are closeDrawer()
and toggleDrawer()
. See pull 3618.
Navigation actions API overhaul
In practice, this change is unlikely to impact your app at all except for one case that is mentioned below.
In 1.x, functions on the navigation
were not contextual - they would be the same regardless of whether your screen was inside of a drawer, a stack, a tab navigator, etc. In 2.0 the functions that are available to you on the navigation
prop depend on the navigators that it corresponds to. If your screen is inside of both a stack and a drawer navigator, you will have helpers for both -- push
and openDrawer
, for example.
Given that we only exposed generic helpers (navigate
, goBack
) and helpers specific to the stack in 1.x, this would only impact you if you attempted to use the stack helpers from outside of a stack. For example, if you had a tab navigator with a stack in tab A and just a plain screen in tab B, then tried to push
a route from the screen in tab B, push
would not be available. Keep this in mind when you update your app if it follows this type of structure.
One of the big improvements you get from this is that you can now add your own helpers to the navigation
prop! Read more in RFC 6 and in pull 3392.
NavigationActions no longer have toString()
implementations (related)
This change was intended to simplify the implementation of actions. We may go back on this, however, and apologize in advance if this thrasing causes you trouble.
NavigationActions split up according to router
If you are using NavigationActions.push
or other stack-specific actions, you’ll need to import StackActions
and use StackActions.push
instead.
Deprecations
XNavigator(...) is now createXNavigator(...)
StackNavigator
, TabNavigator
and DrawerNavigator
are now deprecated in favour of createStackNavigator
, createTabNavigator
, and createDrawerNavigator
, which are functionally identical but more clearly communicate that they are functions and that they return a component. The XNavigator
style will removed in 3.0.
Tab navigator split into separate components
Previously, TabNavigator
would render a navigation bar on the top of the screen on Android and the bottom on iOS. We’ve now pulled these navigators apart, so you can use createBottomTabNavigator
and createMaterialTopTabNavigator
explicitly depending on what you need. You can use createTabNavigator
to have the same behavior as before, but it will be removed in 3.0.
It is worth noting additionally that createBottomTabNavigator
is different from the bottom tab navigator that is available through TabNavigator
in that it does not support animationEnabled
or swipeEnabled
properties.
Enhancements
- dangerouslyGetParent and dismiss helpers on navigation prop (3669)
- State persistence - automatically save state and reload it when the app restarts (3716)
- Smoothly transition header visibility in Stack (3821)
- Add initialRouteKey for StackRouter (3540)
- Make StackNavigator keyboard aware -- it hides automatically when you start to swipe back, and refocuses if you cancel the swipe back gesture (3951)
- Allow modification of SafeAreaView props in header (3496)
- Add
createMaterialBottomTabNavigator
for a material design style tab bar. (see react-navigation-tabs). - Use findIndex instead of map/indexOf in StateUtils (commit
- Warn when users have multiple stateful navigation containers (commit)
- Remove almost all uses of React 16 deprecated lifecycle methods (commit)
- Add
activeLabelStyle
andinactiveLabelStyle
forDrawerItem
(commit)
Bugfixes
- Avoid unnecessary navigation completion dispatches (3902)
- Use Header.HEIGHT instead of measuring to avoid flicker (3940)
- Implement paths on
SwitchRouter
(commit). SwitchRouter
now returnsnull
on idempotent navigation (commit).
Final notes
The breaking changes and deprecations in this release resolve a lot of issues that users have encountered that have been perceived as bugs but were technically expected behavior. We think that we’ve drastically improved library ergonomics for new users and experienced users alike, let us know on Twitter what you think.
We’ve started to plan for 3.0. Please get involved by posting your feature requests to Canny, opening a RFC, or letting us know about bugs with a well-formulated issue!