* Add test for handling null path set on router
* Allow null paths on the router config
Previously if you specified `null` in the router `paths`, the logic would actually fall back to the `path` specified on the route, which is especially bad if the latter is undefined, because then the path would be set as the default of the routeName.
Previous descriptors had been retained because this binding caused `this.prevState` to remain referenced. This binds the component getter to null instead.
* allow key to be undefined on StackNavigation.replace method
* added tests for replace action w/out key
* fix typo
* updated changelog
* updated teests for clarity
* added length check on routes to safely fallthrough to search
React Native 0.56 introduces Flow 0.75, which makes it impossible to refine `NavigationRoute` based on the presence of `index` or `routes` properties.
This PR turns `NavigationStateRoute` and `NavigationLeafRoute` into exact types, which addresses this issue.
Stack router had some aggressive logic for deferring to inactive child routers. The child router behavior should come after all of the appropriate stack actions, with the exception of the active child router.
This was causing issues such as https://github.com/react-navigation/react-navigation/issues/4623 , where inactive tab navigators would handle the back action, and cause the stack to attempt to pop back to it.
* Isolate modules for uncontainerized navigators
* Clean up prop-types
* Fix warnings and web import friendlyness
* strip a flow
* Standalone provider/consumer navigation context
* export shallowEqual as module
* address various lint
# Conflicts:
# src/navigators/createStackNavigator.js
* Get tests to pass
Creating a new error makes the stack unreadable in sentry, because the stack is stringified when the error is cast to string to create a new one.
Is there another reason to do that ?
Alternative possible solution would be to add a method to be able to handle the error ourselves ?
This bug wasnt apparent until we fixed the transitioner to fully respect isTransitioning. The router did not handle this properly until now.
Enhanced a test to verify this in the future
Unrelated change in here: typing `tabBarOnPress`'s `defaultHandler`. Wasn't sure if I should make a separate PR for a single unrelated line, let me know if you'd prefer that going forward.
* Refactor, move child navigation to navigation prop
This fixes our descriptor caching issue, and unblocks explicit nested navigation options.
As a side effect, the following APIs are introduced:
- navigation.getChildNavigation(routeKey) , which is useful for explicitly getting children config info
- navigation.router, access to the static router
- router.childRouters[routeName] , an optional way to access the children routers directly. If childRouters are not provided in a router, we will fall back on getComponentForRouteName(routeName).router, which is the previous external API for this (although it may be slower because it will require the whole screen component).
* supporting tests and top level actions
* cleanup
* Transitioner: Fix instantaneous transitions
The transitioner will always perform an animation on state change. Instead we should check if the navigation state is requesting a transition with isTransitioning. If not, we follow a similar codepath to transitioning, without any animation.
* Update .eslintrc
* Export getNavigationActionCreators
`react-navigation-redux-helpers` generally needs to duplicate whatever `createNavigationCreator` does. As of `react-navigation@2.0`, that includes using `getNavigationActionCreators` to construct the top-level `NavigationScreenProp`.
This PR isn't strictly needed, as it's possible to import from the file directly. But that's a brittle approach, and not particularly discoverable for anybody attempting to use a "non-stateful" navigator with their state management library of choice.
* Further refinements after writing the new helper
* Final refinement of NavigationScreenProp's relationship with _DefaultActionCreators
* Resolve merge conflicts
Using two new utils:
1. `createNavigationPropConstructor`, which is now preferred over `createReduxBoundAddListener`.
2. `initializeListeners`, which is necessary to trigger the event listeners with the initial state.
* [flow] Remove "any" type from NavigationComponent
"any" cripples the typechecker, so it's best to avoid. It was introduced in #3392, but I don't think the intention was to keep it there.
* [flow] Remove `any` type from `createNavigator` return
And use objects with spread sub-types instead of unions for `React$ComponentType` type param
This really is not ideal but it's an upstream bug on react-native Android
that we can't work around. Users may experience other unexpected behavior as a
result of this upstream bug.
Previously we had been emiting an action event with a null state when the router handles the action by returning null from getStateForAction.
- Fixes the case of null state getting emitted
- Renames a few things for clarity
- Refactors conditionals to read easier
- Comments to explain intent
* 3127: Fixed gestureDirectionInverted variable declaration and condition in onPanResponderMove method in regards to swipe back action in RTL mode.
* - 4118: Put axis check first;
- Fixed default BackButton mask in RTL mode.
“reset” is not a NavigationAction anymore.
The correct fix, for v3, to this is to navigate to the first screen inside the stack. With the less-pushy navigate behavior in v2, this will result in the first route getting selected if you specify it by routeName.
* Use Array.prototype.findIndex instead of map => indexOf
Creating a new array and iterating over all the routes is inefficient compared to findIndex, which does not create a new array and exits as soon as it finds a match. Since the indexOf method is used extensively this should provide a minor performance improvement
* reverted yarn.lock edits
* don’t use private global
* add missing method ‘getParam’ to navigation screen prop
* correct return type for ‘withNavigation’
* add usage of `getParam` method
* Make StackNavigator keyboard aware
One thing that has always annoyed me in React Navigation is the handling of the keyboard. When a keyboard is visible on screen and a navigation action occurs (either by tapping a button or using a gesture), the keyboard tends to stay on screen until the transition completes. This feels janky and broken. On native iOS, for instance, the keyboard hides immediately when the navigation starts, and if the transition is cancelled (say, when the user releases the gesture), the keyboard reappears.
This PR introduces a "KeyboardAwareNavigator" higher order component that is enabled on the StackNavigator, unless a `disableKeyboardHandling` prop is passed into the StackNavigator's configuration.
* Set status bar in keyboard handling example
* Call gesture props in keyboard aware navigator if available
* Fix formatting
The navigation prop should also pass through, and be prioritized over context because it is more explicit
This also fixes an incorrect warning/invariant
Adds a new state persistence mechanisms to all of the navigators via createNavigationContainer
There are two new props that you can provide to a navigation container: `storageKey` and `renderLoading`.
`storageKey` is the string key to be used with AsyncStorage while saving and persisting navigation state. To disable persistence, set to null.
`renderLoading` allows you to render something while the navigator re-hydrates its state and loads its initial URL. By default this returns null, but Expo users will want to render a <AppLoading /> component for smooth app launches
There is also functionality in this PR to observe errors that come from re-hydrating state, and gracefully recover by dispatching an init action.
Also this revises the init action to *reset* the navigation state, rather than preserve the previous state.
- It is potentially dangerous because screen components may or may not have the
expected parent, so depending on anything related to the parent may lead to
bugs. You should use carefully because it is dangerous ;)
* Added possibility to provide custom header back button's image, introduced API changes: removed old prop "headerBackImage", added new prop "backImage".
* Code style fixes.
* Renamed showcase file to for more clarity; updated the prop's name as well.
* Removed listeners code from showcase screens.
* wip
* fix imports
* use stylesheet for margin
stylesheet now correct
* also remove old headerLeft
* improve header buttons color
* remove ios button margin
* Add dismiss action, made possible by getParentState
* Add dismiss to flow interface
* Don't dispatch an action on dismiss helper if no parent state
* carefullyGetParent instead of getParentState
1. Remove `NavigationComponent` from `NavigationScreenRouteConfig`. The only context `NavigationScreenRouteConfig` is used in is as an intersection with an object, and as such the only relevant portions of `NavigationScreenRouteConfig` are the object parts.
2. Add static `HEIGHT` variable to `Header` type.
3. In `NavigationContainerProps`, make `onNavigationStateChange` property value nullable.
PS: if in the future you guys would prefer that I separate these sort of PRs into their constituent parts, let me know.
* Add activeLabelStyle and inactiveLabelStyle
Adding activeLabelStyle, so that active items can be customized more.
My use case: Change font of the active item to bold.
Also, added inactiveLabelStyle which can be used for a similar purpose.
* prettier fix
* Update react-navigation.js
* prettier fix
* Update jest snapshot for DrawerNavigator - for adding a new style property to the styles array
* This caches "child event subscribers" by key and removes them when they're not needed anymore. Once a navigator unmounts we also remove upstream subscribers.
* Fix tests
Should be nullable, since it is initially called as `null` in `src/createNavigationContainer.js` (and in `react-navigation-redux-helpers`, where it is causing a Flow error)
* use initialRouteName as key when initializing StackRouter
* fix null headerLeft
* merge back
* fixed tests
* use config flag
* fixed snapshots
* implemented requested changes
* Pop to top when tapping the tab icon for an already focused tab
* Dispatch popToTop with key to scope the action properly
* Add test for POP_TO_TOP with key
* First crack at publish from circle
* s/publish/deploy
* Update snapshots
* Try installing with yarn
* Nice one
* Shhh
* Comment some things out and add a webhook
* Add proper webhook url and add back build steps
* Improve `Header` performance a bit
I have been investigating `<Header />` component performance once again today with `render` cycles in particular. I have observed that during `push` phase, a typical Header in NavigationPlayground re-renders 3 times on iOS and 2 times on Android.
The first time is obvious on both platforms since that's when we add a new scene to an array. Second on iOS was also self-explanatory - we measure title width and other layout parameters in order to provide a better animation.
What got me thinking was the last render cycle that didn't have a clear origin. After digging around I've found it is caused by a `scenes` array changing when transition finishes. What is surprising, it's just the reference to the object that changes, the content (items inside) stay the same.
I have found out that this is caused by `Transitioner` looping through an array of scenes attempting to remove stale scenes. Since scene becomes stale when you `pop` from it, this is obviously a noop when `pushing` a new route. That, obviously, causes an extra render cycle since `filter` produces same, but with a different pointer, object.
* Update Transitioner.js
* Update Transitioner.js
* Move the back button handler subscription to the constructor to fix precedence
- See 07d92947a1/src/Navigation.js (L190-L193)
* Return the boolean result of dispatch in global back handler
* Lazy initialization of tabs and move contents off-screen when not active
* Make subview clipping and lazy both configurable
* Record snapshots again
* Update type definition
* Remove unused log
* add getParam helper
* passing tests
* check for existence of param instead of just or
* fix spacing
* use in instead of checking for null
* add test for null
The most straightforward fix for two issues is to block all navigation actions while mid-transition of a stack navigator. This will fix:
The double-navigate on double tap issue, because the first navigation will start the transition and the second action will be ignored.
Will fix the buggy header experience that you can see when going back and forward to a different route quickly. This happens because the next navigate action happens before the completion action. After the fix, the navigate action will be ignored, the user will tap again, and will see a good transition
Previously the state was getting squashed, in this case it would destroy the routeName of the state, which was a route for the parent navigator, who could no longer render properly.
* Fixing iPad iOS 11 Tab Bar Bottom Behavior with changing widths via Multitasking
* Adding width constrained check
* Moving to only Platform.isPad (no more layout-based tests)
* Remove type import
The completion action would previously change the isTransitioning of any state, but this will ensure that the completing navigator only marks its own state as isTransitioning:false. Now, even when transition completion happens immediately on the parent, the child focus event still waits for the child isTransitioning to go false.
This code was added during the events implementation, but I think we should be able to manage this circumstance from the parent context. In any case, any events bugs that result from this change will be far less insidious than the cardstack transitioner issue we experience now
* Fix invalid easing functions for CardStack
1. `timing` function accepts `TimingAnimationConfig` which expect `easing` (or dont expect at all) function with following signature: `(value: number) => number`
2. under the hood, `TimingAnimation` falls back to `easeInOut` function, if `easing` is not specified
`this._easing = config.easing !== undefined ? config.easing : easeInOut();`
3. by mistake passing `Easing.linear()` results in following
`typeof Easing.linear(); // undefined` which makes statement in step 2 fall back to `easeInOut`
This commit makes passing `easeInOut` function explicit and fixes existing issue and several Flow warnings
* Do not memoize easing function, keep things simple
* Add Flow libdef
* Move libdef to flow folder in root
* Update libdef with some refinements discovered while writing test
Mostly refining navigator config types. In the past when we tried it we got in-repo Flow errors. With a libdef we can now assert it as true!
* Get rid of all imports in libdef and refine some types
In order to make sure that contributors don't making breaking changes to our Flow types without corresponding updates to the libdefs, we should make sure these breaking changes get caught by CI. Right now our libdefs are any-typed, but I'll put up a PR later that will refine the libdef (located at `flow-typed/npm/react-navigation_vx.x.x.js`).
* Fix SimpleTabs types
dca37627a2 broke the types, but it wasn't noticed because Flow wasn't in the CI. This fixes the types; separate PR coming to add Flow to the CI.
* Refine type of NavigationEventListener callback
Instead of typing the callback as `Function`, we're now using the precise type provided by @ericvicenti
* NavigationEventListener -> NavigationEventSubscription
* Add fbemitter, keep flow passing
* Begin support for event emitter
- Adds emitter to navigation prop
- Emits top level onAction event
- stub getChildEventSubscriber for child events
* Support navigationState.isNavigating
* Focus and blur events starting to work
- Navigation completion action wired up
- Event chaining logic built in getChildEventSubscriber
- Renamed onAction evt to ‘action’
* Wrap up events progress and testing
* Rename to isTransitioning and COMPLETE_TRANSITION
* rm accidental dependency
* Suppoert event payload type
- Escape hatch of `ReactNavigation.SafeAreaView.setStatusBarHeight()`.
- `if (Platform.OS === 'android') { ReactNavigation.SafeAreaView.setStatusBarHeight(0) }` to revert to old behavior.
* Fixing iPad iOS 11 Tab Bar Bottom Behavior with changing widths via Multitasking
* Updating snapshot tests
* Changes per discussion in !3041
* Additional changes per discussion in !3041
* Changing to test for constrained height
* Additional changes per discussion in !3041
* Use Animated.View instead of View in SafeAreaView
This allows passing animated style properties in certain contexts, as previously supported.
* Update some test snapshots
`TabRouter.getStateForAction` has some code at the start to initialize an empty nav state before handling any action. This initialization is achieved by passing `INIT` actions to all child routes. However, the code strangely also passes these child routes the params that were given to the action. The initialization should be separate from the processing of the action.
* allow transition configuration between tabs
* we don't need to pass configureTransition to TabBarComponent
* Update TabAnimations.js
* Update TabNavigator.md
* Update to React Native 0.50
* Type Promise used in PlatformHelpers.web.js
* Move $FlowFixMe in CardStack.js
The line number Flow is using for this error changed. The underlying problem has not, but I don't have time to fix it now unfortunately.
* Type TouchableItem's children prop as React.Node
This was my bad. `React.ChildrenArray` should only really be used in the case of having multiple of the same type of child.
* Type HeaderTitle's children prop as React.Node
Same as last commit.
* Add assertion in StackRouter that StateUtils.indexOf returns valid index
Flow doesn't realize that `StateUtils.indexOf` is guaranteed to return a valid index, so we use `invariant` to assert it.
* Remove unused type DrawerNavigationState from TypeDefinition
* Remove unused type parameter T in DrawerView
* Type NavigationStateRoute as NavigationLeafRoute & NavigationState
* Don't constrain generic action types to NavigationAction
By constraining to subtypes of `NavigationAction`, we actually are requiring that any router satisfying our type constraints has to take all of the `NavigationAction` types. Instead, we want to say that it will only take some of them. Changing the types here to be inferred.
* Fix types of NavigationScreenProp and withCachedChildNavigation
1. `NavigationScreenProp` needs to have its type parameter annotated with a `+` to actually indicate covariance on that type parameter, apparently
2. `withCachedChildNavigation` needs to thread through more-specific `NavigationState`s, and right now it just discards that specificity, which breaks `DrawerSidebar` because it needs a `NavigationStateRoute`
* Ignore website/build from Flow
* Fix type of DrawerItems activeItemKey prop
- Even when specified, it can be `null`
- Use a ternary expression instead of `x && x.param` approach
* Get rid of NavigationRouter & NavigationNavigator parameterization on NavigationAction
Since `NavigationRouter`'s `getStateForAction` functionality is a standard Redux reducer, it knows to forward on any actions it doesn't know how to deal with. We can widen the types of these functions to be `NavigationAction` without any negative consequence.
* Explicitly specify null navigationOptions in createNavigator
Not sure why, but Flow doesn't like us leaving it unspecified
* Fix createNavigationContainer/createNavigator/StackNavigator types
* Fix up flow types for TabNavigator and DrawerNavigator
* Properly type defaultContentComponent
* Fix more flow errors in createNavigationContainer
* Replace NavigatorProps with NavigationNavigatorProps
* Type SceneView's navigation prop as NavigationScreenProp<any>
There is an unavoidable* type problem here. A `NavigationComponent` is either a navigator with a `NavigationStateRoute` or a scene with a `NavigationRoute`. The navigation prop it gets passed must match the component's `NavigationState`. However, there's no way for us to say that "`this.props.router.getComponentForRouteName` will have a `NavigationNavigator` iff the corresponding `childNavigationProps` is a `NavigationStateRoute`".
The cleanest way to make this work is to throw an "any" specifically for the navigation prop's state type param.
* We could probably avoid it with sufficient refactoring. If the routers were charged with keeping track of `childNavigationProps` instead of leaving it to the views, they could return the child navigation prop and child `NavigationComponent` in pairs whose types were coupled.
* Pass in screenProps to NavigationComponent in NavigationPlayground's CustomTabs
Flow wants `screenProps` to be passed in here for some reason...
It cites `SceneView`, but that doesn't really make much sense to me. But this is some custom logic that most people aren't likely to run into, so I'm not gonna worry too much about it.
* Patch mismatch with react-native-tab-view type for now
* Use generic NavigationState in createNavigationContainer's _nav var
We made the NavigationState generic while #1313 added a new instance variable. This updates the new instance variable to be generic.
* Fix failing tests
In React Fiber (React 16), strings are used for intrinsics like 'div' and 'View'. As a result, if you use a View as a screen in an academic experience, you get a red error screen. This PR prevents that from happening.
* Fix default width of drawer
Current implementation is simplified / broken.
- The drawerWidth doesn't work for tablets, the drawer becomes massively large
- Header size changes (and thus drawer width changes) in landscape mode on iOS are not accounted for
- An incorrect 64px header size is used for iOS (this includes the status bar height that doesn't belong in the calculation)
Implement a default drawerWidth as a function that follows the Material Design spec closer:
- Screen width - header height
- Use the correct iOS app bar height in portrait and landscape mode
- Drawer max height of 280 on mobile and 320 on tablet
* Update snapshot for drawer width change
* Move SafeAreaView out of DrawerNavigatorItems to DrawerSidebar.
The SafeAreaView was breaking custom contentContainers in drawers. Fixes#2963.
* Fix SafeAreaView in DrawerItems and Drawer contentComponent
* Fix flow error and tests.
* Update Drawer documentation with SafeAreaView recommendation. Remove one of the examples for `contentComponent`.
* Put the View back.
* Update snapshot.
this react-native error has no adequate stack, and i waste 4 hours for juggling pieces, until i get the idea to trace error by myself and finded this bug
* add 2nd params argument to StackRouter.getActionForPathAndParams
It still falls back to parsing the query string if no params argument is provided, but now TabRouter.getActionForPathAndParams which might call StackRouter.getActionForPathAndParams with a 2nd params argument will work correctly.
In addition, if called directly (as may be the case in apps with custom deep-linking needs [which is my primary case]), it will function correctly without users having to build a query string.
This also solves the problem that deserialization of query strings is currently implemented without support for cases like nested arrays within the query string.
* Update StackRouter.js
* SafeAreaView now adds padding from style object. If height is specified, inset padding is added to height.
* Header now only accepts headerStyle prop, backgroundColor works as expected.
* TabBarBottom now only accepts style prop, backgroundColor works as expected. Fixes top inset bug.
* Update snapshot.
* Add clarifying comment.
* Support padding with percentage.
Fixes second part of issue #2854.
`itemsContainerForceInset` takes the same object as `forceInset` on SafeAreaView. It overrides the SafeAreaView container in DrawerItems.
* Add SafeAreaView - JS only version
* Add SafeAreaView
* Looking pretty good
* Small refactor
* Remove console.log
* Fix merge conflict with Header flow types.
* Fix conflict with itemsContainerStyle.
* Fix merge conflict.
* Fix merge conflict, yarn and package.json from fixflow
* Fix merge conflict, navigation playground yarn.lock and package.json with fixflow
* Now it can work on lower versions of RN
* Snapshots merge conflict.
* Update DrawerNavigator snapshot.
* Fix conflict with iconContainerStyle
* Add support for correct status bar height on iPad.
* Update jest snapshots.
* Update StackNavigator snapshot.
* Use modulo instead of while
* Fix landscape tab bar width on < iOS 11
* Update root package to react-native@0.49 and flow-bin@0.53
* Update NavigationPlayground package to react-native@0.49 and flow-bin@0.53
* Update ReduxExample package to react-native@0.49 and flow-bin@0.53
* flow-typed update (code-gen)
* Find-and-replace old types with new types
- `React.Element<*>` as the result of a render function is now `React.Node`
- `ReactClass<T>` as the type of a Component is now `React.ComponentType<typeof T>`
- `extends React.Component<DP, P, S>` is now `extends React.Component<P, S>`
- `React.Children<*>` as the type of a children prop is now `React.ChildrenArray<*>`
- Refs are now typed with `React.Ref`
There are also several tiny typo fixes in here.
* Avoid assuming state is NavigationRoute in addNavigationHelpers
For the root, top-level Navigator, the state is a simple `NavigationState` (with no route info) and we still use `addNavigationHelpers` for it. We can't assume `navigation.state.key` is accessible for this type, so we need to do runtime checks here.
* Fix type of NavigationScreenConfig
`navigationOptions` was incorrectly typed
* Give createNavigationContainer's State a type parameter
We want to be able to specifically type this guy so we can use specific NavigationState for things like the Drawer views without having to do runtime assertions about the state type
* Fix typing of NavigationAction
First of all, `NavigationAction` was being used as two different types, so I had to create the new `PossiblyDeprecatedNavigationAction` and add it as a type parameter everywhere. Second of all, generics and implied types were being used far more than they need to be, and they're hard to work with because Flow doesn't really explain things well when they go wrong.
* Make sure children scenes of CardStack have NavigationProp typed with NavigationRoute
CardStack's `NavigationScreenProp` is typed with `NavigationState`, but the children need `NavigationRoute`. Flow gets confused by the spread operator, even if the individual property is replaced later, so we need to explicitly list each property individually (just `dispatch`, actually).
* Allow prevTransitionProps parameter to be nullable
* Allow prevTransitionProps parameter to be nullable
* Narrow down a couple type parameters
* Move NavigationStateRoute cast to within Component.router check in createConfigGetter
* Update withCachedChildNavigation so it's typed correctly with React.ComponentType
* Add a $FlowFixMe for displayName
`React.StatelessFunctionalComponent` is missing `displayName` before Flow 0.54.0
See de37062ea2
* Make TouchableItem's onPress prop optional
`HeaderBackButton` can pass in an undefined onPress, and the React Native `Touchable*` components allow it too
* Simplify withCachedChildNavigation and get rid of generics
The generics don't help us here and they make the types more confusing
* Redefine NavigationComponent as direct intersection
The new type is technically identical to the old type, but Flow is confused by the old type...
* Save router to local var before checking createConfigGetter
Flow seems to think Component.router can change after the check
* Fix DrawerSidebar's navigation prop's type
In order for us to be able to generate a childNavigationProp, the original navigation prop has to have a NavigationState state.
* Colocate action.key check with action.type check in getStateForAction
For some reason, Flow thinks `action` can change sometime after `action.type` is checked. As a result, it's not properly concluding that `action.key` should exist. To avoid this, we pull `action.key` out immediately after doing the `action.type` check.
* Use bounded polymorphism to pass down all props in withCachedChildNavigation
Also makes sure the injected props are specified first in the union
Also removes an unused `eslint-disable-line` in `getScreenForRouteName`
* Make TabRouter's getComponentForState return NavigationComponent
`NavigationScreenComponent` is a subtype of `NavigationComponent`, but it's not clear that `getComponentForState` always returns a `NavigationScreenComponent`, as `getScreenForRouteName` returns `NavigationComponent`
* Define NavigationComponent's props using NavigationNavigatorProps
Right now the types ask Flow to infer the types of `NavigationComponent`'s props. (`NavigationComponent` is the union of `NavigationNavigator` and NavigationScreenComponent.) Instead, we type the props as subtypes of `NavigationNavigatorProps`, so we can properly access those props without type errors. We used bounded polymorphism in `createNavigationContainer` and `createNavigator` to pass down these props. We also explicitly type the action in `createNavigationContainer` so we can properly pass in a `NavigationInitAction` to the dispatch function.
* Parameterize NavigationTabRouterConfig
`NavigationTabRouterConfig` doesn't always take `NavigationTabScreenOptions`; sometimes, it takes `NavigationDrawerScreenOptions`.
* Make all NavigationOptions Exact types
We're seeing weird behavior when these are merged together. By making them Exact types, we make types don't get mangled when they're unioned.
https://flow.org/en/docs/types/unions/#toc-disjoint-unions-with-exact-types
* Silence errors in tests
These errors are unavoidable since we can't type the precise shape of a particular `NavigationState`.
* Include NavigationSetParamsAction in NavigationTabAction
`TabNavigator`'s `getStateForAction` definitely takes `NavigationSetParamsAction`.
* Explicitly list router as void in NavigationScreenComponent
This is so Flow knows that if a `NavigationComponent` has a `router` property, then it is definitely a `NavigationNavigator`.
* Fix website app navigator's type
* Fix createDocPage type in App
In an earlier commit I attempted to fix the types here, but I incorrectly read it as returning a navigator when it just returns a screen. For some reason the error didn't immediately show up.
* Fix NavigationComponent types
Five changes:
1. No longer parameterizing the props of `NavigationComponent`; directly specifying as `NavigationNavigatorProps`
2. Specify the two distinct kinds of route types (leaf and state) directly in `NavigationComponent`
3. Have `SceneView` directly take `NavigationComponent` and allow inferring of `NavigationSceneProp` type
4. Have `CardStack` directly take `NavigationComponent` as well
* Allow Flow to infer `NavigationAction` type in `createNavigator`
* Silence Flow in router code that handles navigator sub-routes
There's no way for us to tell Flow that routes that correspond to navigators should be `NavigationStateRoute`s
* Allow DrawerSidebar to take a null contentComponent
The way `DrawerNavigator` is set up, it's possible to pass in a null `contentComponent` in the config.
If somebody want to do this, we'll just make the `DrawerSidebar` not appear altogether. This is simpler than splitting the types so there's a possibly-unspecified one for the user input, but a definitely-specified one in `DrawerSidebar`.
* Specify missing screenProps prop in DrawerView
* Thread full NavigationStateRoute in to DrawerSidebar
This requiring making `withCachedChildNavigation` use bounded polymorphism to thread the `NavigationStateRoute` through instead of downgrading it to a `NavigationState`
* Make NavigationStateProp's state prop covariant
This means that `NavigationStateProp<NavigationStateRoute>` will be a subtype of `NavigationStateProp<NavigationRoute>` and `NavigationStateProp<NavigationState>`
* Silence Flow's complaints about a route not being a NavigationStateRoute
As mentioned in previous commits and in the comment, there is no way to type a specific navigation state shape, so we have to cast it and silence Flow's complaints.
* Get rid of style prop in CardStack
It looks like at some point, it was possible to specify a `style` prop that got passed all the way down to `Header`, the `TransitionConfig`'s `screenInterpolator`, and `Transitioner`. Doesn't look like we're using it anywhere, and there's a todo saying to remove it, and it's causing a type error.
* Infer type of options instead of using a subtype of {}
I think this has to do with {} allowing for unsealed objects. I'm not 100% sure, but this fixes 4/6 of the remaining errors!
* Fix two type errors in NavigationPlayground
One was just requiring an outdated type (`React.Children` instead of `React.ChildrenArray`), and the other was getting confused regarding types because of a spread operator.
* Use a covariant property to simplify withCachedChildNavigation's InputProps
This doesn't reduce any errors, but it's a bit simpler and cleaner.
* Silence last two Flow errors regarding withCachedChildNavigation injecting childNavigationProps
These are the only two errors I haven't been able to figure out at all. If I had more time I'd try and figure out the simplest case and report it to the Flow team, but I've been working on this for a week already and have to move on.
The issue at hand is that `withCachedChildNavigation` injects `childNavigationProps`, but Flow doesn't see this and thinks it needs to be specified by the view component. We're using the HOC pattern suggested by the Flow docs, and I've tried several other patterns to no avail.
* Use stock react-native instead of Expo's in NavigationPlayground
Expo's causes Flow errors, and apparently this is normal practice because the person who switched us to Expo did this too.
* Silence react-native-gesture-handler Flow errors in NavigationPlayground
Expo requires this package, but it causes Flow errors.
* Fix index check in DrawerSidebar
Silly me, falling for the typical "0 is falsey" problem...
* Rework deprecated action tests
In an earlier commit I moved the `NavigationActions.mapDeprecatedActionAndWarn` out from `getStateForAction` and into `createNavigationContainer`'s `dispatch` function. The tests need to be reworked to support this, as they were previously calling `getStateForAction` directly. I don't imagine any users are calling `getStateForAction` directly.
* Re-record two snapshots
The changes in these snapshots are by design and don't affect anything.
* Infer type of options in NavigationScreenConfig
The issue is that sometimes we include options for different navigators in a single blob.
* Infer types of action and options in createNavigationContainer
Particulary helps with Options. Makes the types more specific and gets rid of an error that only shows up when using the library
* Don't use generics for NavigationState in createNavigationContainer
There's no particular reason for having those generics there, since there's no way we'd be able to get Flow to understand the exact shape of particular navigation states anyways. This fixes a bug when integrating this version of the project into my repo.
* Move ReduxExample to react-native@0.49.3 instead of custom Expo version
* Fix animation (#1493)
* Rewrite the file animatedInterpolate.js. To increase readability.
* Rename the variable, To increase readability.
* minor renaming
* Pass transition and modal props to transitionConfigurer
* Make arguments passed to transitionConfigurer required
* Update docs with params passed to transitionConfigurer
* Give docs some more room to breath
* Working on the new docs
* New intro
* Writing installation guide
* Finish tab intro.
* Write intro to drawernavigator.
* Add some space
* Rename guide
* Minimize changes
* Fix links
* Edits
* Fixes default drawerWidth to match material ui patterns.
Previously: calculated based on device width regardless of orientation and did not recalculate when orientation changed.
Now: calculates based on minimum of device height/width, remains constant and guaranteed to always fit screen regardless of orientation.
This is the expected behavior based on observing Google apps (e.g. Gmail). This is also better than recalculating on every orientation change, which would result in variable width drawers and awkward empty space when in landscape in most cases.
* Remove console.log
* Handle the ios11 tabbar correctly
* Fix an issue when showLabel is false
* Add a basic test for the tabbarbottom
* Add check for ios version number
* Tests shall pass
* make things work for all the versions
* Again, fix the tests
* added property inside drawerConfig to backgroundColor (drawerBackgroundColor)
* Adjusting documentation for PR deployment (# 2698)
* add example in the doc
* fix issue #2251 by including queryString to get nested action
* only use nested query string when original queryString exists, and include test cases
* Fixing Intro Guide
Fixes#832 - the code in this page was wrong, that export default was causing errors.
I've also modified a few phrases here and there to help the comprehension.
* more fixes, for CRNA
the problem I see with many bug reports in this repo is that people write a very vague description of what their problem is and expect to get some help. I tried to:
1 . emphasise how important it is to include a runnable reproduction
2 . cut down on some extra words at the beginning of the template so it's more to the point
* Fix .flowconfig to stop ignoring modules and properly include React Native libraries
Currently, there are numerous ignored libraries that are hiding type errors. Actually, they're causing type errors too. This sort of thing only patches over actual problems, so we have to revert them to get a config we can build upon.
* Update react-native/flow-bin dependencies
We want to have Flow types working with the latest packages.
* Update flow-typed libraries (auto-generated)
* Fix typing of navigation prop used by withNavigation HOC
The current typing is clearly a typo, as it is circular. `NavigationScreenProp` should be used to type the navigation prop
* Fix typing of easing function
What's funny is that I fixed this before in d71ed75133. @skevy reintroduced the mistyped function in 9436d03fe8, which didn't trigger any Flow errors because .flowconfig was ignoring the entire react-native package
* Correct typing of View and Text style prop
The current code thinks it can import these, but this isn't true, and was being hidden because the .flowconfig ignored the whole react-native package. There's no easy to type Text and View at the current moment, as far as I can tell. Importing the highly generic `StyleObj` seems like the best bet, and is what I have being using in my projects.
* Import NavigationScreenComponent using full path
* Updating yarn.lock files
* Get rid of library overrides in flow-typed/react-native.js and flow/react-navigation.js
* Add @flow to src/react-navigation.js and make last three params to createNavigator optional
* Make screenProps and navigationOptions optional in NavigationNavigatorProps
* yarn run format
* Readd react-navigation/node_modules ignore to NavigationPlayground's .flowconfig
Realized this line I removed in the first commit is necessary when using npm link/yarn link, which is what the CircleCI build does
* Make all DrawerViewConfig's params optional
Some of these params are marked as optional because they have defaults. However, the only place `DrawerViewConfig` is used is as the input the function that then applies the defaults
* Make all props in NavigationNavigatorProps optional
`NavigationNavigatorProps` is used to type the props of the component that is output by the `StackNavigator`, `TabNavigator`, etc. component factories. This component does not need to have any props specified.
* Make second param to `DrawerNavigator` factory optional
`DrawerNavigator`, just like `TabNavigator` and `StackNavigator`, can be called with just a single argument (ie. omitting the config)
* Upgrade to RN 0.48.4 to address https://github.com/facebook/react-native/issues/15810
* added drawerLockMode with cabilities to update it on the fly
* fixed incorrect name on markdown for usage
* added handling if screenProps is not being used
* Fix linting error
* Use drawerLockMode instead of lockMode
* Correct docs
* Fix flow issues
* Make drawerLockMode optional
* Mock and verify console warnings to prevent noise in the test output.
* Tighten up expectations on deprecation output.
* 80 column formatting.
* Actually fix formatting.
* Ignore the jest setup file when calculating test coverage.
* Actually collect coverage from the whole library codebase so that the numbers are actually useful.
Previously, we were creating an anonymous function as the event listener handler. This means we can't un-listen because we don't have a reference to the handler.
* [ReduxExample] Delete android and ios dirs
* [ReduxExample] Upgrade using create-react-native-app
* [ReduxExample] Add postinstall script to clean up files Yarn copies in
Yarn copies them when installing locally, causing lots of @proviesModule collisions.
* [ReduxExample] Upgrade expo and other dependencies
* [ReduxExample] Don't delete .git just in case
* Update .eslintrc to allow compile.
* Resolve .web.js extension
* Look for __DEV__ on global
Fixes ReferenceError when not in the React Native environment.
* Replace __DEV__ at compile time via babel
* Don't try to lint a website build
* [Playground] Commit auto-changes to package.json, yarn.lock
* [Playground] Rerun create-react-native-app
Preserving rn-cli.js and transformer.js
Still not quite working.
* [Playground] Fix the Expo loading issue by removing projectRoots
Now it looks in the right place to find its resources, including 'entryPoint'.
* [Playground] Add postinstall script to clean up files Yarn copies in
Yarn copies them when installing locally, causing lots of @providesModule collisions.
* Update the Contributors guide to explain how to use the example app
And recommend Yarn by default
* [Playground] Remove now-obsolete rn-cli.config.js
* [Playground] Upgrade expo and other dependencies
* [Playground] Don't delete .git just in case
Because react-native-tab-view insists on sticking at 0.0.*,
the caret version pinning won't install "minor" updates.
Semver rules are weird with 0. major versions.
Is this something you'd be interested in?
* Add additional guidance information to the GitHub issue template.
- Provides links to best places to ask usage questions.
- Uncomments guiding information in issue template that wasn't visible when creating issue.
- Based on questions asked here: https://new-issue.vuejs.org/#modal
* Remove ' instead of the expected behavior'
* fixed bug with wrong label&icon in Drawer
* itemPress in Drawer now always navigates to first screen of a nested StackRouter
* used eslint formatting
* added comments
macOS creates metadata files named `.DS_Store`. The script incorrect tries to read it with a `.md` extension. By excluding all files that start with a dot we can prevent this.
After having to look for a solution for nesting a navigator embedded in a component, found this issue that dealt with the same problem: https://github.com/react-community/react-navigation/issues/90.
Added the solution to the guide as a side note.
previously when opening a deeplink without a path, it would result in an array of 2 empty strings, which is are falsy values, so the full url was passed on.
by checking if the value is actually `undefined` instead of falsy we have no more false positives
Use the new Docker-based, beta version of CircleCI.
This adds a docker image that has the correct deps to run flow, and then migrates from the old circle.yml format to the new.
This gets test runs wayyyyy down. Earlier today, on the old stack, before optimizations, we were at > 9 min for PR builds (aka, CI runs without a website deploy). The build for this PR ran in 1 min 33 seconds. Woo!
* Navigation actions should be string literals to work properly with Flow
* Update StackRouter/TabRouter tests with eslint ignore rule
* Use `expect.objectContaining` so we don't rely on keys
* Update Stacks{In,Over}Tabs example for better clarity
* Remove redundant navigationOptions in stack examples
* Update text in ReduxExample to clarify which route is being used
This Init{index} pattern guarantees that the same keys will always be re-used when doing a RESET.
This behaviour doesn’t match how the rest of the router works and causes bugs.
Namely if you are on `{ routeName: ‘Dashboard’, params: { user: ‘A’ } }` and use RESET to `{ routeName: ‘Dashboard’, params: { user: ‘B’ } }` when the user switches, it will act like a `setParams` action instead of a `RESET` action and the Dashboard will not be re-mounted.
to allow composition of the Header component when using a custom header
component, styling is probably one of the options you want to have.
For example, I need to dynamicly change the height of the header based
on scroll position, and without this change I have to inherit from the
Header component and copy the render function, instead of composing the
Header component in my own component.
If you attempt to use something other than a string, it will throw an error in some situations. #1318 provides more details about the error. If it is expecting a certain type, the docs should clarify that.
* add headerBackTitleStyle screen option
since the title is customizable, the back title should too.
* add documentation for `headerBackTitleStyle`
* make absence of headerBackTitle not affect return value
* merge styles so current scene can override
If there's no last scene, return the `headerBackTitleStyle` from the
current scene.
Otherwise return the `headerTitleStyle` from the last scene, and the
`headerBackTitleStyle` from the current scene, with the latter having
precedence.
* take headerBackTitleStyle from current scene
also the title style of the last scene is no longer taken into account
* Implement getPathAndParamsForState for StackRouter
* Add test to make sure `params` is correct in getPathAndParamsForState of StackRouter
* chore: fix flow
* Fix Modal Gestures
* Update StackNavigator.md for gesturesEnabled to include modals again
* Remove modal gesture todo
* Gesture response distance top, side => vertical, horizontal
* [ReduxExample] Programmatically generate initial state
* [ReduxExample] Return original state if nextState is null
* [Docs] Add getStateForAction to redux integration example
* [Docs] Add link to ReduxExample app
* [Docs] Give each example a 'DRY' README linking to real docs
* [Docs] Clean up the Contributors guide a bit
* [Docs] Remove numbers from sections in Contributors guide
They don't seem very meaningful, and don't need to be done in order
* Force the back button to be recognized as such by screen readers.
* Update HeaderBackButton.js
* Update HeaderBackButton.js
* Update HeaderBackButton.js
* Format remaining issues
* [Example] Get tests passing on ReduxExample and NavigationPlayground
* [CI] Use more vague versioning so we're always up to date
* [CI] Test that the example apps run without error
* [CI] Install the current local version of react-nav before testing
* Fix tabs => spaces in ReduxExample/package.json
* Remove LinkingExample entirely
It's now part of NavigationPlayground.
* [Example] Upgrade dependencies to fix the ReduxExample app
* [Example] Also upgrade and fix the LinkingExample app
* [Example] Update MainApplication.java to fix Android API
Centered titles are generally specific to iOS, left alignment of the title appears more common in platforms outside Android and iOS.
This also fits better with the rest of the conditionals that test for iOS instead of Android.
`screenProps` were not being passed to `CardStack` and consequently not
available for the navigationOptions function in components using
`StackNavigator`.
* Initial commit
* Remove HybridExample (#985)
* Remove HybridExample
* Remove last mention of HelloHybrid
* Remove console log
* Fix flow and example
* Fix routers api docs
* Keep options in single place
* chore
* Fix styling
* Organise miscs
* Better flow type for screen options
* Flow test website and add more types to options
* navigationOptions instead of prevOptions makes more sense
* Fixes
* Fix up docs
* Fix
* Update route decl
* Provide error when removed API is used
* Remove lock
* Add validators
* Make StacksOverTabs config valid again
* Do not return
* Fix redbox
* [Example] Fix the ReduxExample app
Just a bit of cleanup so it can run.
* [Example] Remove AsyncStorage persistence from ReduxExample
It's a cool feature, but isn't necessary to demonstrate how to use
react-navigation and may cause more confusion than it's worth.
* [Playground] Duplicate StacksInTabs to StacksOverTabs
* [Playground] Move nested routes into root stack so they appear on top
* [Playground] Go to SettingsTab instead of pushing a new Settings screen
* [Redux example] Use HTTPS-enabled endpoint to get npm modules
To fix 'yarn install'
* [Redux example] Add ReduxExample to rn-cli.config.js
This prevents those annoying @providesModule naming collisions
* [Examples] Add a basic README linking to the usage instructions
* First test
* Allow a key to be passed for which scene should handle the action
* Adding key to NavigationResetAction
* Added test
* Add reset test with key
* Only apply this change if it is a RESET action
* Fix logic error, only check if the action is null if it is a RESET
* Added option to overwrite label style for only if label is as string defined in navigationOptions in DrawerNavigation.
* update doc for labelStyle prop
* change title to label
`ReactComponentWithPureRenderMixin` is useless in this file, and it has been removed from the core of latest `react`
build fails on master branch of `react-native` for this error
The example provides styling for the tab icon via the `icon` property in the styles object. However in the example, it is used as `tabIcon` which does not exist.
* add import to clarify source of helper
It took me a while to figure out where 'addNavigationHelpers' comes from, maybe adding the import in the doc here will help the next guy.
* add spaces around imported value
* removed empty line
* Change the way we store computed layout
We cannot store layouts under `index` because when calling `replace`, there are two competing layouts
on the same index, which will cause an infinite loop (are almost infinite) of flickering / jumping title.
* Disable transition at all when index didn't change
* Initial impl
* Fix up some docs and support more for drawer
* Fix comments
* Support TabBar
* Make flow more correct
* Clarify even more
* Rename all the things lol
* Also rename renderLabel to getLabel
* Removed Navigation Containers and containerOptions
Cut out text to move to navigators docs page
* Moved nav containers section to Navigators API docs
When the drawer opens / close, the result of AppNavigator.router.getStateForAction(action, state); is null. So the nav state in the store is null which causes errors. This solves that.
Per request [#228](https://github.com/react-community/react-navigation/issues/228), I've updated the the Hello Mobile Navigation guide to try and make it more approachable to newcomers like myself. I changed the order of some of the explanations and broke out passing params into its own section. This should make the guide easier to follow as only one new concept is introduced per section; a common principle in teaching methodology.
I'm open to suggestions as I am also a newcomer to both React Native and React Navigation. So it's very possible that there are concepts that I've misunderstood or am not explaining well.
Fixes: Named import from module `../TypeDefinition` `ContextWithNavigation` is a type, but not a value. In order to import it, please use `import type`.
## The issue tracker is reserved for bug reports only.
If you have a question, feature request, or an idea for improving the library or its related tools, please try one of the following resources:
- [Read the documentation](https://reactnavigation.org/)
- [Post an issue to the website repository if you'd like to see a documentation change](http://github.com/react-navigation/website)
- [Post a feature request to Canny](https://react-navigation.canny.io/feature-requests)
- [Write a RFC if you have ideas for how to implement a feature request](https://github.com/react-navigation/rfcs)
- [Get help on Discord chat (#react-navigation on Reactiflux)](https://discord.gg/4xEK3nD) or [on StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation)
- Search for your issue - it may have already been answered or even fixed in the development branch. However, if you find that an old, closed issue still persists in the latest version, you should open a new issue.
Bugs with react-navigation must be reproducible *without any external libraries that operate on it*. This means that if you are attempting to use Redux or MobX with it and you think you have found a bug, you must be able to reproduce it without Redux or MobX in this report. Redux related issues belong in [react-navigation-redux-helpers](https://github.com/react-navigation/react-navigation-redux-helpers), and we do not have any first-class integration with MobX at the moment.
---
### Current Behavior
- What code are you running and what is happening?
- Include a screenshot if it makes sense.
### Expected Behavior
- What do you expect should be happening?
- Include a screenshot if it makes sense.
### How to reproduce
- You must provide a way to reproduce the problem. If you are having an issue with your machine or build tools, the issue belongs on another repoistory as that is outside of the scope of React Navigation.
- Either re-create the bug on [Snack](https://snack.expo.io) or link to a GitHub repository with code that reproduces the bug.
- Explain how to run the example app and any steps that we need to take to reproduce the issue from the example app.
Please provide enough information so that others can review your pull request:
## Motivation
Explain the **motivation** for making this change. What existing problem does the pull request solve?
## Test plan
Demonstrate the code is solid. Example: the exact commands you ran and their output, screenshots / videos if the pull request changes UI.
Make sure you test on both platforms if your change affects both platforms.
The code must pass tests.
## Code formatting
Look around. Match the style of the rest of the codebase. Run `yarn format` before committing.
## Changelog
Add an entry under the "Unreleased" heading in [CHANGELOG.md](https://github.com/react-navigation/react-navigation/blob/master/CHANGELOG.md#unreleased) which explains your change.
-`lazy` and `optimizationsEnabled` options to `createMaterialTopTabNavigator` (react-navigation-tabs@0.6.0)
### Fixed
- Android back button in stack with drawer closes drawer properly if open (react-navigation-drawer@0.5.0)
- Fixes bug where `null` doesn't work in routerOptions `paths` object for deeplinking ([#4791](https://github.com/react-navigation/react-navigation/pull/4791))
- Export `StackViewTransitionConfigs` to allow you to extend default config in custom transition configs. [#4761](https://github.com/react-navigation/react-navigation/pull/4761)
### Fixed
- Error when building with haul: ref to pathToRegexp.compile(#4658).
- Error when building with haul: ref to pathToRegexp.compile. [#4658](https://github.com/react-navigation/react-navigation/pull/4658).
- Incorrect parameters passed to title offset calculation led to bug in header layout when no right component (https://github.com/react-navigation/react-navigation/issues/4754)
-`headerLayoutPreset: 'center' | 'left'` to provide an easy solution for [questions like this](https://github.com/react-navigation/react-navigation/issues/4615).
-`headerBackTitleEnabled` - this configuration option for stack navigator allows you to force back button titles to either be rendered or not (if you disagree with defaults for your platform and layout preset).
### Fixed
- Android back button ripple is now appropriately sized (fixes [#3955](https://github.com/react-navigation/react-navigation/issues/3955)).
- Respect header background color on container (fixes edge case where user depended on displaying content that was rendered behind the navigator, this particular behavior should not be depended on and may break in the future, but this change is still useful regardless).
-`headerLeftContainerStyle`, `headerTitleContainerStyle`, and `headerRightContainerStyle` are exposed on `navigationOptions`. These properties allow you to customize the style of the container of `headerLeft`, `headerTitle` and `headerRight` components.
### Fixed
- Fixed memory leaks in `createNavigator`: [closure scope leak](https://github.com/react-navigation/react-navigation/commit/1a765562905e93bbae0262dd20c2688221c999e8), and [clean up old descriptors](https://github.com/react-navigation/react-navigation/commit/93642e16e7ff029586b68ee732ec790504ee4862).
- The enableURLHandling prop on the top level navigator component allows you to disable deep linking handling. Currently it is always enabled. To disable it, `<RootNavigator enableURLHandling={false} />`
### Changed
- StackNavigator.replace method no longer requires a key param. If the key is left undefined, the last screen in the stack will be replaced.
### Fixed
- Support headerLeft component for the first screen in a stack (#4608).
- Removed bottomBorder when `headerTransparent` is set to true.
- Improve empty path and param handling in deep linking (#4671). This fixes issues with deep linking and fully tests the differences between path: '' and path: null. Empty string matches empty paths, and null path will let the child router handle paths at the same level. Also it makes sure that params are not duplicated between path and query when they are serialized with getPathAndParamsForState.
- Fix onTransitionStart not being invoked when provided in navigator config.(#4100)
- Rare case when users navigated back and forth quickly with exactly the right timing would cause a crash due to a scene being queued to transition, then clobbered, then attempted to render as a stale scene but without a descriptor. ([commit](https://github.com/react-navigation/react-navigation/commit/cab4d71a5e09188df3f4a294c98779eecb860a78))
- [NavigationEvents](https://github.com/react-navigation/react-navigation/pull/4188) component as a declarative interface for subscribing to navigation focus events.
- Avoid crash when calling isFocused on old route (https://github.com/react-navigation/react-navigation/commit/0921889f7a3acfc6d6bcc4909d209eeeee985ba7)
- Stack router no longer attempts to parse query params within path handling
- Switch router now has exact same param treatment for URLs as stack router does
### Changed
- Internally we no longer need to special case PlatformHelpers by platform as react-native-web handles the APIs we mocked out with it now.
- Throw error in development mode when header navigation option is set to a string - a common mistake that would otherwise result in a cryptic error message.
- Throw error in development mode when title is not a string.
### Fixed
- Delegate to child routers for more than just the top screen in the stack.
- Update react-navigation-drawer to 0.4.3 to fix `initialRouteParams` option
-`setParams` applies to the navigation object it is called on even if that is the navigation object for a navigation view (more details in https://github.com/react-navigation/react-navigation/issues/4497)
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at adam@expo.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
A lot of developers poured their knowledge in blog posts, and other repos - we will try to keep here a list of resources to help someone who wants to learn about React Navigation and techniques to handle navigation effectively.
#### Introduction to the library
* [Getting Started with React Navigation](https://hackernoon.com/getting-started-with-react-navigation-the-navigation-solution-for-react-native-ea3f4bd786a4)
#### Basic Tutorials
* [Basic ReactNavigation Example App and Tutorial](http://docs.nativebase.io/docs/examples/navigation/StackNavigationExample.html)
* [Understanding Navigation in React Native](https://www.codementor.io/blessingoraz/understanding-navigation-in-react-native-a3wlcxmzu?published=1#.WXfDlvk_ooE.twitter)
* [Comprehensive routing and navigation in React Native made easy](https://medium.com/@kevinle/comprehensive-routing-and-navigation-in-react-native-made-easy-6383e6cdc293)
* [Replace a Screen Using React Navigation](https://medium.com/handlebar-labs/replace-a-screen-using-react-navigation-a503eab207eb)
#### Intermediate Concepts
* [Integrating React-Navigation and Redux with authentication flow](https://medium.com/@shubhnik/a-comprehensive-guide-for-integrating-react-navigation-with-redux-including-authentication-flow-cb7b90611adf)
* [Using React Navigation and Redux in your React Native Application](https://medium.com/modus-create-front-end-development/using-react-navigation-and-redux-in-your-react-native-application-efac33265138)
* [React-Navigation, complete Redux state management, tab-bar, and multiple navigators](https://medium.com/@parkerdan/react-navigation-with-complete-redux-state-management-tab-bar-and-multiple-navigators-ed30a69d9a4d)
* [Custom Drawer with React-Navigation in React-Native](http://www.skywardsoftwares.co.in/react-native/custom-drawer-with-react-navigation-in-react-native/)
* [React Navigation Drawer - a tutorial series](https://shift.infinite.red/react-navigation-drawer-tutorial-a802fc3ee6dc)
#### Advanced Topics
* [Full Stack React Native Development using GraphCool and Apollo Subscriptions + React Navigation](https://medium.com/react-native-training/full-stack-react-native-development-using-graphcool-and-apollo-subscriptions-react-navigation-cdb3e1374c05)
#### Comparisons and Discussion
* [Migrate from ExNavigation to React Navigation](https://hackernoon.com/migrate-from-exnavigation-to-react-navigation-1af661ec5082)
* [Playing with React Navigation and Airbnb's Native Navigation](https://medium.com/@ericvicenti/playing-with-react-navigation-and-airbnbs-native-navigation-4e49fc765489)
* [How we restructured our app with React Navigation](https://m.oursky.com/how-we-restructured-our-app-with-react-navigation-98a89e219c26)
* [What’s Happening with Navigation in React Native?](https://blog.revisify.com/whats-happening-with-navigation-in-react-native-c193535888c3)
This library is a community effort: it can only be great if we all help out in one way or another! If you feel like you aren't experienced enough using React Navigation to contribute, you can still make an impact by:
* Responding to one of the open [issues](https://github.com/react-community/react-navigation/issues). Even if you can't resolve or fully answer a question, asking for more information or clarity on an issue is extremely beneficial for someone to come after you to resolve the issue.
* Creating public example repositories or [Snacks](https://snack.expo.io/) of navigation problems you have solved and sharing the links in [Community Resources](https://github.com/react-navigation/react-navigation/blob/master/COMMUNITY_RESOURCES.md).
* Answering questions on [Stack Overflow](https://stackoverflow.com/search?q=react-navigation).
* Answering questions in our [Reactiflux](https://www.reactiflux.com/) channel.
* Providing feedback on the open [PRs](https://github.com/react-navigation/react-navigation/pulls).
* Providing feedback on the open [RFCs](https://github.com/react-navigation/rfcs).
* Improving the [website](https://github.com/react-navigation/react-navigation.github.io).
If you would like to submit a pull request, please follow the [Contributors guide](https://reactnavigation.org/docs/contributing.html) to find out how. If you don't know where to start, check the ones with the label [`good first issue`](https://github.com/react-community/react-navigation/labels/good%20first%20issue) - even [fixing a typo in the documentation](https://github.com/react-community/react-navigation/pull/2727) is a worthy contribution!
Please provide enough information so that others can review your pull request:
Explain the **motivation** for making this change. What existing problem does the pull request solve?
Prefer **small pull requests**. These are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise split it.
**Test plan (required)**
Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI.
Make sure you test on both platforms if your change affects both platforms.
The code must pass tests and shouldn't add more Flow errors.
**Code formatting**
Look around. Match the style of the rest of the codebase.
* The best way to learn is to follow the [Getting started guide](https://reactnavigation.org/docs/getting-started.html). It guides you through the fundamentals of React Navigation.
* The documentation includes solutions for common use cases in the "How do I do ...?" section, such as [tab navigation](https://reactnavigation.org/docs/tab-based-navigation.html) and [Redux integration](https://reactnavigation.org/docs/redux-integration.html).
* If you need to build your own navigator, [there's a section for that](https://reactnavigation.org/docs/custom-navigator-overview.html) too.
* The [API reference](https://reactnavigation.org/docs/api-reference.html) lists all public APIs.
* The [Community Resources](https://github.com/react-navigation/react-navigation/blob/master/COMMUNITY_RESOURCES.md) document lists some other resources submitted to us by people who use React Navigation. Feel free to open a pull request to add your resource to the list.
* You can contribute improvements to the documentation [in the website repository](https://github.com/react-navigation/react-navigation.github.io).
You can also try out the [Navigation Playground app](https://exp.host/@react-navigation/NavigationPlayground) to get a sense for some of the tools built in to React Navigation. The "Fundamentals" in the documentation also include examples you can play with.
## FAQs
#### I'm having troubles using the library, what can I do?
See [the help page](https://reactnavigation.org/en/help.html).
#### How can I help?
See our [Contributing Guide](CONTRIBUTING.md)!
#### Is this the only library available for navigation?
Certainly not! There other libraries - which, depending on your needs, can be better or worse suited for your project. Read more in the [alternative libraries](https://reactnavigation.org/docs/alternatives.html) documentation, and read React Navigation's [pitch & anti-pitch](https://reactnavigation.org/docs/pitch.html) to understand the tradeoffs.
#### Can I use this library for web?
Web support was [not a priority for the 1.0 release](https://github.com/react-community/react-navigation/issues/2585#issuecomment-330338793), but the architecture of this library allows for it (and it has worked in the past). If you would like to lead this charge, please reach out with your ideas for how to move forward on the [RFCs repository](https://github.com/react-navigation/rfcs) and we would be happy to discuss.
## Code of conduct
This library has adopted a Code of Conduct that we expect project participants to adhere to. Please read the [full text](https://github.com/react-community/react-navigation/blob/master/CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated.
## License
React Navigation is licensed under the [BSD 2-clause "Simplified" License](https://github.com/react-community/react-navigation/blob/master/LICENSE).
The route configs object is a mapping from route name to a route config, which tells the navigator what to present for that route, see [example](https://github.com/coodoo/react-navigation/blob/master/docs/api/navigators/StackNavigator.md#routeconfigs) from `StackNavigator`.
### DrawerNavigatorConfig
-`drawerWidth` - Width of the drawer
-`drawerPosition` - Options are `left` or `right`. Default is `left` position.
-`contentComponent` - Component to use to render the navigation items. Receives the `navigation` prop for the drawer. Defaults to `DrawerView.Items`.
-`contentOptions` - Configure the drawer content, see below.
Several options get passed to the underlying router to modify navigation logic:
-`initialRouteName` - The routeName for the initial route.
-`order` - Array of routeNames which defines the order of the drawer items.
-`paths` - Provide a mapping of routeName to path config, which overrides the paths set in the routeConfigs.
-`backBehavior` - Should the back button cause switch to the initial route? If yes, set to `initialRoute`, otherwise `none`. Defaults to `initialRoute` behavior.
### `contentOptions` for `DrawerView.Items`
-`activeTintColor` - label and icon color of the active label
-`activeBackgroundColor` - background color of the active label
-`inactiveTintColor` - label and icon color of the inactive label
-`inactiveBackgroundColor` - background color of the inactive label
-`style` - style object for the content section
#### Example:
```js
contentOptions:{
activeTintColor:'#e91e63',
style:{
marginVertical:0,
}
}
```
### Navigator Props
The navigator component created by `DrawerNavigator(...)` takes the following props:
-`screenProps` - Pass down extra options to child screens, for example:
```jsx
const DrawerNav = DrawerNavigator({
// config
});
<DrawerNav
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
Navigators allow you define you application's navigation structure. Navigators also render common elements such as headers and tab bars which you can configure.
Under the hood, navigators are plain React components.
## Built-in Navigators
`react-navigation` includes the following functions to help you create navigators:
- [StackNavigator](/docs/navigators/stack) - Renders one screen at a time and provides transitions between screens. When a new screen is opened it is placed on top of the stack.
- [TabNavigator](/docs/navigators/tab) - Renders a tab bar that lets the user switch between several screens
- [DrawerNavigator](/docs/navigators/drawer) - Provides a drawer that slides in from the left of the screen
## Rendering screens with Navigators
The navigators render application screens which are just React components.
To learn how to create screens, read about:
- [Screen `navigation` prop](/docs/navigators/navigation-prop) to allow the screen to dispatch navigation actions, such as opening another screen
- [Screen `navigationOptions`](/docs/navigators/navigation-options) to customize how the screen gets presented by the navigator (e.g. header title, tab label)
### Calling Navigate on Top Level Component
In case you want to use Navigator from the same level you declare it you can use react's [`ref`](https://facebook.github.io/react/docs/refs-and-the-dom.html#the-ref-callback-attribute) option:
Provides a way for your app to transition between screens where each new screen is placed on top of a stack.
By default the StackNavigator is configured to have the familiar iOS and Android look & feel: new screens slide in from the right on iOS, fade in from the bottom on Android. On iOS the StackNavigator can also be configured to a modal style where screens slide in from the bottom.
-`title` - a title (string) displayed in the header
-`header` - a config object for the header bar:
-`visible` - Boolean toggle of header visibility. Only works when `headerMode` is `screen`.
-`title` - Title string used by the navigation bar, or a custom React component
-`right` - Custom React Element to display on the right side of the header
-`left` - Custom React Element to display on the left side of the header
-`style` - Style object for the navigation bar
-`titleStyle` - Style object for the title component
-`tintColor` - Tint color for the header
### Navigator Props
The navigator component created by `StackNavigator(...)` takes the following props:
-`screenProps` - Pass down extra options to child screens, for example:
```jsx
const SomeStack = StackNavigator({
// config
});
<SomeStack
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>
```
### Examples
See the examples [SimpleStack.js](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground/js/SimpleStack.js) and [ModalStack.js](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground/js/ModalStack.js) which you can run locally as part of the [NavigationPlayground](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground) app.
The route configs object is a mapping from route name to a route config, which tells the navigator what to present for that route, see [example](https://github.com/coodoo/react-navigation/blob/master/docs/api/navigators/StackNavigator.md#routeconfigs) from `StackNavigator`.
### TabNavigatorConfig
-`tabBarComponent` - component to use as the tab bar, e.g. `TabView.TabBarBottom`
(this is the default on iOS), `TabView.TabBarTop`
(this is the default on Android)
-`tabBarPosition` - position of the tab bar, can be `'top'` or `'bottom'`
-`swipeEnabled` - whether to allow swiping between tabs
-`animationEnabled` - whether to animate when changing tabs
-`lazyLoad` - whether to lazily render tabs as needed as opposed to rendering them upfront
-`tabBarOptions` - configure the tab bar, see below.
Several options get passed to the underlying router to modify navigation logic:
-`initialRouteName` - The routeName for the initial tab route when first loading
-`order` - Array of routeNames which defines the order of the tabs
-`paths` - Provide a mapping of routeName to path config, which overrides the paths set in the routeConfigs.
-`backBehavior` - Should the back button cause a tab switch to the initial tab? If yes, set to `initialRoute`, otherwise `none`. Defaults to `initialRoute` behavior.
### `tabBarOptions` for `TabBarBottom` (default tab bar on iOS)
-`activeTintColor` - label and icon color of the active tab
-`activeBackgroundColor` - background color of the active tab
-`inactiveTintColor` - label and icon color of the inactive tab
-`inactiveBackgroundColor` - background color of the inactive tab
-`showLabel` - whether to show label for tab, default is true
-`style` - style object for the tab bar
-`labelStyle` - style object for the tab label
Example:
```js
tabBarOptions:{
activeTintColor:'#e91e63',
labelStyle:{fontSize:12},
style:{
backgroundColor:'blue',
}
}
```
### `tabBarOptions` for `TabBarTop` (default tab bar on Android)
-`activeTintColor` - label and icon color of the active tab
-`inactiveTintColor` - label and icon color of the inactive tab
-`showIcon` - whether to show icon for tab, default is false
-`showLabel` - whether to show label for tab, default is true
-`upperCaseLabel` - whether to make label uppercase, default is true
-`pressColor` - color for material ripple (Android >= 5.0 only)
-`pressOpacity` - opacity for pressed tab (iOS and Android <5.0only)
Routers define a component's navigation state, and they allow the developer to define paths and actions that can be handled.
## Built-In Routers
`react-navigation` ships with a few standard routers:
- [StackRouter](/docs/routers/stack)
- [TabRouter](/docs/routers/tabs)
## Using Routers
To make a navigator manually, put a static `router` on a component. (To quickly make a navigator with a built-in component, it may be easier to use a [Navigator Factory](/docs/navigators) instead)
```js
classMyNavigatorextendsReact.Component{
staticrouter=StackRouter(routes,config);
...
}
```
Now you can use this component as a `screen` in another navigator, and the navigation logic for `MyNavigator` will be defined by this `StackRouter`.
## Customizing Routers
See the [Custom Router API spec](/docs/routers/api) to learn about the API of `StackRouter` and `TabRouter`. You can override the router functions as you see fit:
### Custom Navigation Actions
To override navigation behavior, you can override the navigation state logic in `getStateForAction`, and manually manipulate the `routes` and `index`.
You can make your own router by building an object with the following functions:
```js
constMyRouter={
getStateForAction:(action)=>({}),
getActionForPathAndParams:(path,params)=>null,
getPathAndParamsForState:(state)=>null,
getComponentForState:(state)=>MyScreen,
getComponentForRouteName:(routeName)=>MyScreen,
};
// Now, you can make a navigator by putting the router on it:
classMyNavigatorextendsReact.Component{
staticrouter=MyRouter;
render(){
...
}
}
```

### `getStateForAction(action, state)`
Defines the navigation state in response to a given action. This function will be run when an action gets passed into `props.navigation.dispatch(`, or when any of the helper functions are called, like `navigation.navigate(`.
Typically this should return a navigation state, with the following form:
```
{
index: 1, // identifies which route in the routes array is active
routes: [
{
// Each route needs a name to identify the type.
routeName: 'MyRouteName',
// A unique identifier for this route in the routes array:
key: 'myroute-123',
// (used to specify the re-ordering of routes)
// Routes can have any data, as long as key and routeName are correct
...randomRouteData,
},
...moreRoutes,
]
}
```
If the router has handled the action externally, or wants to swallow it without changing the navigation state, this function will return `null`.
### `getComponentRouteName(routeName)`
Returns the child component or navigator for the given route name.
Say a router `getStateForAction` outputs a state like this:
```js
{
index:1,
routes:[
{key:'A',routeName:'Foo'},
{key:'B',routeName:'Bar'},
],
}
```
Based on the routeNames in the state, the router is responsible for returning valid components when calling `router.getComponentRouteName('Foo')` or `router.getComponentRouteName('Bar')`.
### `getComponentForState(state)`
Returns the active component for a deep navigation state.
### `getActionForPathAndParams`
Returns an optional navigation action that should be used when the user navigates to this path and provides optional query parameters.
### `getPathAndParamsForState`
Returns the path and params that can be put into the URL to link the user back to the same spot in the app.
The path/params that are output from this should form an action when passed back into the router's `getActionForPathAndParams`. That action should take you to a similar state once passed through `getStateForAction`.
### `getScreenConfig`
Used to retrieve the navigation options for a route. Must provide the screen's current navigation prop, and the name of the option to be retrieved.
-`navigation` - This is the navigation prop that the screen will use, where the state refers to the screen's route/state. Dispatch will trigger actions in the context of that screen.
-`optionName` - What named option is being fetched, such as 'title'
Inside an example view, perhaps you need to fetch the configured title:
```js
// First, prepare a navigation prop for your child, or re-use one if already available.
constchildNavigation=addNavigationHelpers({
// In this case we use navigation.state.index because we want the title for the active route.
Manage the logical navigation stack, including pushing, popping, and handling path parsing to create a deep stack.
Let's take a look at a simple stack router:
```js
constMyApp=StackRouter({
Home:{screen:HomeScreen},
Profile:{screen:ProfileScreen},
},{
initialRouteName:'Home',
})
```
### RouteConfig
A basic stack router have a route config. Here is an example configuration:
```js
constMyApp=StackRouter({// This is the RouteConfig:
Home:{
screen:HomeScreen,
path:'',
},
Profile:{
screen:ProfileScreen,
path:'profile/:name',
},
Settings{
// This can be handy to lazily require a screen:
getScreen:()=>require('Settings').default,
// Note: Child navigators cannot be configured using getScreen because
// the router will not be accessible. Navigators must be configured
// using `screen: MyNavigator`
path:'settings',
},
});
```
Each item in the config may have the following:
-`path` - Specify the path and params to be parsed for item in the stack
-`screen` - Specify the screen component or child navigator
-`getScreen` - Set a lazy getter for a screen component (but not navigators)
### StackConfig
Config options that are also passed to the stack router.
-`initalRouteName` - The routeName for the default route when the stack first loads
-`initialRouteParams` - Default params of the initial route
-`paths` - Provide a mapping of routeName to path config, which overrides the paths set in the routeConfigs.
### Supported Actions
The stack router may respond to the following navigation actions. The router will generally delegate the action handling to a child router, if possible.
- Navigate - Will push a new route on the stack if the routeName matches one of the router's routeConfigs
- Back - Goes back (pops)
- Reset - Clears the stack and provides new actions to create a fully new navigation state
- SetParams - An action that a screen dispatches to change the params of the current route.
// Note: Child navigators cannot be configured using getScreen because
// the router will not be accessible. Navigators must be configured
// using `screen: MyNavigator`
path:'settings',
},
});
```
Each item in the config may have the following:
-`path` - Specify the path for each tab
-`screen` - Specify the screen component or child navigator
-`getScreen` - Set a lazy getter for a screen component (but not navigators)
### Tab Router Config
Config options that are also passed to the router.
-`initialRouteName` - The routeName for the initial tab route when first loading
-`order` - Array of routeNames which defines the order of the tabs
-`paths` - Provide a mapping of routeName to path config, which overrides the paths set in the routeConfigs.
-`backBehavior` - Should the back button cause a tab switch to the initial tab? If yes, set to `initialRoute`, otherwise `none`. Defaults to `initialRoute` behavior.
### Supported Actions
The tabs router may respond to the following navigation actions. The router will generally delegate the action handling to a child router, if possible.
- Navigate - Will jump to the routeName if it matches a tab
- Back - Goes to the first tab, if not already selected
- SetParams - An action that a screen dispatches to change the params of the current route.
`Transitioner` is a React component that helps manage transitions for complex animated components. It manages the timing of animations and keeps track of various screens as they enter and leave, but it doesn't know what anything looks like, because rendering is entirely deferred to the developer.
Under the covers, `Transitioner` is used to implement `CardStack`, and hence the `StackNavigator`.
The most useful thing `Transitioner` does is to take in a prop of the current navigation state. When routes are removed from that navigation state, `Transitioner` will coordinate the transition away from those routes, keeping them on screen even though they are gone from the navigation state.
## Example
```jsx
classMyNavViewextendsComponent{
...
render(){
return(
<Transitioner
configureTransition={this._configureTransition}
navigation={this.props.navigation}
render={this._render}
onTransitionStart={this.onTransitionStart}
onTransitionEnd={this.onTransitionEnd}
/>
);
}
```
## Props
### `configureTransition` function
Invoked on `Transitioner.componentWillReceiveProps`, this function allows customization of animation parameters such as `duration`. The value returned from this function will be fed into a timing function, by default `Animated.timing()`, as its config.
// An easing function from `Easing`, default: Easing.inOut(Easing.ease)
easing:Easing.bounce,
}
}
```
Note: `duration` and `easing` are only applicable when the timing function is `Animated.timing`. We can also use a different timing function and its corresponding config parameters, like so:
-`transitionProps`: the current [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the current navigation state and props
-`prevTransitionProps`: the previous [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the previous navigation state and props
#### Returns
- An object of type [NavigationTransitionSpec](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L316) that will be fed into an Animated timing function as its config
### `navigationState` object
A plain object that represents the navigation state
#### Example value
```js
{
// Index refers to the active child route in the routes array.
For more information about the `NavigationRoute` type, check out its [flow definition](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L32).
### `render` function
Invoked from `Transitioner.render()`. This function performs the actual rendering delegated from `Transitioner`. In this function, we can use the information included in the `transitionProps` and `prevTransitionProps` parameters to render scenes, create animations and handle gestures.
There are a few important properties of the `transitionProps` and `prevTransitionProps` parameters that are useful for the tasks mentioned above:
-`scenes: Array<NavigationScene>` - a list of all available scenes
-`position: NavigationAnimatedValue` - the progressive index of the transitioner's navigation state
-`progress: NavigationAnimatedValue` - the value that represents the progress of the transition when navigation state changes from one to another. Its numberic value will range from 0 to 1.
For the complete list of properties of `NavigationTransitionProps`, check out its [flow definition](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273).
#### Examples
`transitionProps.scenes` is the list of all available scenes. It is up to the implementor to determine how to lay them out on the screen. For example, we can render the scenes as a stack of cards like so:
We can then use an `Animated.View` to animate the transition. To create necessary animated style properties, such as `opacity`, we can interpolate on `position` and `progress` values that come with `transitionProps`:
```jsx
_renderScene(transitionProps,scene){
const{position}=transitionProps;
const{index}=scene;
constopacity=position.interpolate({
inputRange:[index-1,index,index+1],
outputRange:[0,1,0],
});
// The prop `router` is populated when we call `createNavigator`.
The above code creates a cross fade animation during transition.
For a comprehensive tutorial on how to create custom transitions, see this [blog post](http://www.reactnativediary.com/2016/12/20/navigation-experimental-custom-transition-1.html).
-`transitionProps`: the current [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the current state and props
-`prevTransitionProps`: the previous [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the previous state and props
#### Returns
- A ReactElement, which will be used to render the Transitioner component
### `onTransitionStart` function
Invoked when the transition animation is about to start.
-`transitionProps`: the current [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the current state and props
-`prevTransitionProps`: the previous [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the previous state and props
Navigation views are presentation components that take a [`router`](/docs/api/routers) and a [`navigation`](/docs/navigators/navigation-prop) prop, and can display several screens, as specified by the `navigation.state`.
Navigation views are controlled React components that can present the current navigation state. They manage switching of screens, animations and gestures. They also present persistent navigation views such as tab bars and headers.
## Built in Views
- [CardStack](https://github.com/react-community/react-navigation/blob/master/src/views/CardStack.js) - Present a stack that looks suitable on any platform
+ [Card](https://github.com/react-community/react-navigation/blob/master/src/views/Card.js) - Present one card from the card stack, with gestures
+ [Header](https://github.com/react-community/react-navigation/blob/master/src/views/Header.js) - The header view for the card stack
- [Tabs](https://github.com/react-community/react-navigation/blob/master/src/views/TabView) - A configurable tab switcher / pager
- [Drawer](https://github.com/react-community/react-navigation/tree/master/src/views/Drawer) - A view with a drawer that slides from the left
## [Transitioner](/docs/views/transitioner)
`Transitioner` manages the animations during the transition and can be used to build fully custom navigation views. It is used inside the `CardStack` view. [Learn more about Transitioner here.](/docs/views/transitioner)
[`withNavigation`](/src/views/withNavigation.js) is a Higher Order Component which passes the `navigation` prop into wrapped Component. It's useful when you cannnot pass the `navigation` prop into into the component directly, or don't want to pass it in case of a deeply nested child.
## Example
```js
import{Button}'react-native';
import{withNavigation}from'react-navigation';
constMyComponent=({to,navigation})=>(
<Buttontitle={`navigate to ${to}`}onPress={()=>navigation.navigate(to)}/>
Today we're excited to introduce React Navigation, a flexible navigation library for React Native and web, including customizable views for React Native, routers for any platform, and navigators that make it super easy to get started. We aim to provide a simple and extensible solution which enables developers to share one navigation paradigm for all of their React apps.
## Start Quick with pre-built Navigators
A navigator is a React component with a static `.router` declared on it. To make it super easy to get started, React Navigation ships with a few navigator factories, pairing common views with routers.
For example, the provided `StackNavigator` makes it easy to use a `CardStack` view and a `StackRouter` together:
```js
constMyApp=StackNavigator({
Home:{screen:HomeScreen},
Profile:{screen:ProfileScreen},
});
```
Each of these screens are just React components, and they can easily set their own title:
```js
classHomeScreenextendsReact.Component{
staticnavigationOptions={
title:'Home',
};
render(){
const{navigate}=this.props.navigation;
return(
<Button
onPress={()=>navigate('Profile',{name:'A'})}
title="Go to A's profile"
/>
);
}
}
```
To learn more, [continue with the getting started guide](/docs/intro).
## Performant Views on React Native
Animations and gestures are critical for smooth navigation in a mobile app. React Navigation utilizes React Native's Animated library to provide 60fps animations that are driven from the native thread.
The views are designed to be highly extensible. For your app, you may want to build a custom modal, fork the stack header, or even utilize the underlying `<Transitioner>` component to build an entirely custom navigation presentation.
## Routers for Every Platform
In React Navigation, routers manage the [relationship between actions, state, and URIs](/docs/routers/api). The routers are cross-platform, and there is example code for iOS, Android, and web. Several routers are included, including [`TabRouter`](/docs/routers/tab) and [`StackRouter`](/docs/routers/stack), and it is encouraged to [override their behavior as needed](/docs/routers).
The routers are composable and can be useful for structuring your app. A common navigation structure in iOS is to have an independent navigation stack for each tab, where all tabs can be covered by a modal. This is three layers of router: a card stack, within tabs, all within a modal stack. So unlike our experience on web apps, the navigation state of mobile apps is too complex to encode into a single URI. Routers in `react-navigation` map from URIs to navigation actions, which are then used to compute navigation state.
## Future
React Navigation is born from the React Native community's need for an extensible yet easy-to-use navigation solution. It replaces and improves upon several navigation libraries in the ecosystem, including Ex-Navigation and React Native's Navigator and NavigationExperimental components.
Until the community lands on one navigation solution that works well on the web and React Native, we will forever be destined to re-invent navigation. We are extremely sensitive about the burden of change that accompanies a new navigation library, so we aim to provide a solution that will work long into the future. We are excited to support React Navigation for any platform, including cutting-edge frontiers like hybrid native apps, web server rendering, and ReactVR.
The first beta of React Navigation is available today on npm and GitHub, and you can [get started here](/docs/intro). We're excited to hear feedback from the React community, and together we still have a long way to go before our dream is realized. We'd love to see the community flourish with beautiful navigation views, custom router integrations, and more easy-to-use navigators. All of these individual contributions can work together seamlessly. If you have improvements for the built-in components, please [follow the contributors guide](/docs/guides/contributors) and dive right in!
It is useful to have “one standard way” to handle navigation in a React app. Unfortunately, we've learned that a single navigation library cannot be the right fit for every application. There is often a tradeoff between several useful features:
* Simplicity
* Supporting complex animations
* Navigating between natively-implemented screens and JavaScript screens
* Precise fidelity to the native UI controls
* Default support for deep linking and the Android back button
Although the React Native community will need more than one navigation library, we can make them work nicely together. The goal of this document is to specify a common API for navigation libraries. Consistency will make several things easier for React Native developers:
* Combining multiple navigation libraries in one application
* Switching out navigation libraries when requirements change
* Learning navigation once, and applying that knowledge in different applications
Navigation libraries don't have to implement all of this API - it's just a recommendation.
(TODO: When we actually publish this spec, we should mention here what libraries are supporting it, what libraries will support it, and (link to?) how to migrate from other now-discouraged navigation libraries.)
## Key Concepts
#### Navigation Container
The parent component which hosts a navigation-aware component. It must provide the `navigation` prop, and usually uses the child component's static `router` to determine navigation state.
#### Navigation-Aware Component
A React component which can observe and initiate navigation in an app. It uses the navigation prop to see navigation state and request actions. It may expose a router to define navigation state and URI handling.
The card stack of your application may be a navigation-aware component. Also, one screen of your app that handles the Android back button is a navigation-aware component.
#### Navigation State
The object that defines the navigation state of your component, passed in as a prop. A router can define the state, which optionally specifies the title and URI of the component.
#### Action
A JSON object used to request changes in the app's navigation state.
#### Router
Defines the navigation behavior of a component by defining navigation state as a function of actions, and allows URIs to be optionally converted into an action that can be handled.
#### Navigator
A navigation-aware component that hosts other navigation-aware components. Most navigators are expected to delegate all router logic, manage child navigation state, and pass up actions as they are dispatched.
## Specification
### The `navigation` prop
The navigation prop should be provided to components who need access to navigation. If provided, it must follow this interface:
The controlled navigation state prop, as requested by the parent.
```javascript
constMyView=({navigation})=>{
switch(navigation.state.myRequestedView){
case'ViewA':return<ViewA/>;
case'ViewB':return<ViewB/>;
default:return<OtherView/>;
}
}
```
#### navigation.dispatch(action)
The channel that a component can call to request navigation from its parent. When calling `dispatch`, you must provide an action object with a `type`. There are two special action types: 'Navigation/BACK' and 'Navigation/URI'.
```javascript
constMyLink=({navigation})=>(
<ButtononPress={()=>{
navigation.dispatch({
type:'MyNavigationRequest',
myParam:42,
});
}>
Pressmetonavigate
</Button>
);
```
### The static `router`
A router object may be statically defined on your component. If defined, it must follow this interface:
The state and action types of the static router must match the state and action types associated with the navigation prop passed into the component.
#### router.getStateForAction(action, lastState)
This function is defined on the static router and is used to define the expected navigation state.
```javascript
classScreenWithEditModeextendsReact.Component{
staticrouter={
getStateForAction:(action,prevState)=>{
return{isEditing:true};
},
};
render(){
// this.props.navigation.state.isEditing === true
...
}
}
```
`getStateForAction` must **always** return a navigation state that can be rendered by the component when passed in as the `navigation.state` prop.
If null is returned, we are signaling that the previous navigation state has not changed, but the action is handled. This is usually used in cases where the action is being swallowed.
#### router.getActionForURI(uri)
Return an action if a URI can be handled, otherwise return `null`
### Special Actions
There are two special actions that can be fired into `navigation.dispatch` and can be handled by your `router.getStateForAction`.
#### Back Action
This action means the same thing as an Android back button press.
```
type BackAction = { type: 'Navigation/BACK' };
```
#### URI Open Action
Used to request the enclosing app or OS to open a link at a particular URI. If it is a web URI like `http` or `https`, the app may open a WebView to present the page. Or the app may open the URI in a web browser. In some cases, an app may choose to block a URI action or handle it differently.
```
type URIAction = { type: 'Navigation/URI', uri: string };
```
### Special Navigation State
The state defined by `router.getStateForAction` can contain special navigation properties that may be relevant to your app. The title and current URI of a component may change over time, and the parent often needs to observe the behavior.
#### `state.title`
If the navigation state contains 'title', it will be used as the title for the given component. This is relevant for top-level components on the web to update the browser title, and is relevant in mobile apps where a title is shown in the header.
#### `state.uri`
A URI can also be put in `state.uri`, which will signal to the parent how it may be possible to deep link into a similar navigation state. In web apps, this will be used to keep the URI bar in sync with the current navigation state of the app.
## Use Cases
### "Block the Android back button on one screen of my app"
To block the Android back button:
```
class Foo extends React.Component {
static router = {
getStateForAction(action, prevState = {}) {
if (action.type === 'Navigation/BACK') return null;
else return prevState;
},
};
render() {
...
```
Because we return null, we signal to our container that the action has been handled but the state does not change. The parent should not handle the back behavior at this point, and nothing should be re-rendered.
if (action.type === 'GoDeep') return { deep: true };
else return prevState;
},
getActionForURI(uri) {
if (uri === 'myapp://foo')
return {type: 'Go'};
else if (uri === 'myapp://foo_deep')
return {type: 'GoDeep'};
return null;
},
};
render() {
// this.props.navigation.state.deep may be true or false
...
```
Based on the state URI we may decide to return an action. If an action is returned, `getStateForAction` is expected to output the correct state for a deep link.
## Reference Implementations
A library to that helps easily produce navigation-aware components: https://github.com/react-community/react-navigation . (Also uses a HOC to provide navigation containers when needed.)
A simple navigation container: https://gist.github.com/ericvicenti/77d190e2ec408012255937400e34bdb1
A web implementation of a navigation container: https://gist.github.com/ericvicenti/55bef95fcd8558029a3bae8483baea6c
React navigation was initially developed on macOS 10.12, with node 7+, and react-native v0.39+. Please open issues when uncovering problems in different environments.
To run the website in production mode with server rendering:
```
npm run prod
```
### 3. Run tests, run flow
```
jest
flow
```
Tests must pass for your changes to be accepted and merged.
Flow is not yet passing, but your code should be flow checked and we expect that your changes do not introduce any flow errors.
### 4. Developing Docs
The docs are indexed in [App.js](https://github.com/react-community/react-navigation/blob/master/website/src/App.js), where all the pages are declared alongside the titles. To test the docs, follow the above instructions for running the website. Changing existing markdown files should not require any testing.
The markdown from the `docs` folder gets generated and dumped into a json file as a part of the build step. To see updated docs appear in the website, re-run the build step by running `npm run build-docs` from the `react-navigation` root folder.
## Submitting Contributions
### New views or unique features
Often navigation needs are specific to certain apps. If your changes are unique to your app, you may want to fork the view or router that has changed. You can keep the source code in your app, or publish it on npm as a `react-navigation` compatible view or router.
This library is intended to include highly standard and generic navigation patterns. But it
### Major Changes
Before embarking on any major changes, please file an issue describing the suggested change and motivation. We may already have thought about it and we want to make sure we all are on the same page before starting on any big changes.
### Minor Bugfixes
Simple bug fixes are welcomed in pull requests! Please check for duplicate PRs before posting.
A navigator is any React component that has a [router](/docs/routers/) on it. Here is a basic one, which uses the [router's API](/docs/routers/api) to get the active component to render:
```js
classMyNavigatorextendsReact.Component{
staticrouter=MyRouter;
render(){
const{state,dispatch}=this.props.navigation;
const{routes,index}=state;
// Figure out what to render based on the navigation state and the router:
The navigation prop passed down to a navigator only includes `state` and `dispatch`. This is the current state of the navigator, and an event channel to send action requests.
All navigators are controlled components: they always display what is coming in through `props.navigation.state`, and their only way to change the state is to send actions into `props.navigation.dispatch`.
Navigators can specify custom behavior to parent navigators by [customizing their router](/docs/routers/). For example, a navigator is able to specify when actions should be blocked by returning null from `router.getStateForAction`. Or a navigator can specify custom URI handling by overriding `router.getActionForPathAndParams` to output a relevant navigation action, and handling that action in `router.getStateForAction`.
### Navigation State
The navigation state that is passed into a navigator's `props.navigation.state` has the following structure:
```
{
index: 1, // identifies which route in the routes array is active
routes: [
{
// Each route needs a name, which routers will use to associate each route
// with a react component
routeName: 'MyRouteName',
// A unique id for this route, used to keep order in the routes array:
key: 'myroute-123',
// Routes can have any additional data. The included routers have `params`
...customRouteData,
},
...moreRoutes,
]
}
```
### Navigation Dispatchers
A navigator can dispatch navigation actions, such as 'Go to a URI', 'Go back'.
The dispatcher will return `true` if the action was successfully handled, otherwise `false`.
## Navigation Containers
The built in navigators can automatically behave like top-level navigators when the navigation prop is missing. This functionality provides a transparent navigation container, which is where the top-level navigation prop comes from.
When rendering one of the included navigators, the navigation prop is optional. When it is missing, the container steps in and manages its own navigation state. It also handles URLs, external linking, and Android back button integration.
For the purpose of convenience, the built-in navigators have this ability because behind the scenes they use `createNavigationContainer`. Usually, navigators require a navigation prop in order to function.
### `containerOptions`
These options can be used to configure a navigator when it is used at the top level.
An error will be thrown if a navigator is configured with `containerOptions` and also receives a `navigation` prop, because in that case it would be unclear if the navigator should handle its own state.
-`URIPrefix` - The prefix of the URIs that the app might handle. This will be used when handling a [deep link](/docs/guides/linking) to extract the path passed to the router.
## API for building custom navigators
To help developers implement custom navigators, the following utilities are provided with React Navigation:
### `createNavigator`
This utility combines a [router](/docs/routers/) and a [navigation view](/docs/views/) together in a standard way:
```js
constMyApp=createNavigator(MyRouter)(MyView);
```
All this does behind the scenes is:
```js
constMyApp=({navigation})=>(
<MyViewrouter={MyRouter}navigation={navigation}/>
);
MyApp.router=MyRouter;
```
### `addNavigationHelpers`
Takes in a bare navigator navigation prop with `state` and `dispatch`, and augments it with all the various functions in a screen navigation prop, such as `navigation.navigate()` and `navigation.goBack()`. These functions are simply helpers to create the actions and send them into `dispatch`.
### `createNavigationContainer`
If you want your navigator to be usable as a top-level component, (without a navigation prop being passed in), you can use `createNavigationContainer`. This utility will make your navigator act like a top-level navigator when the navigation prop is missing. It will manage the app state, and integrate with app-level nav features, like handling incoming and outgoing links, and Android back button behavior.
In this guide we will set up our app to handle external URIs. Let's start with the SimpleApp that [we created in the getting started guide](/docs/intro).
In this example, we want a URI like `mychat://chat/Taylor` to open our app and link straight into Taylor's chat page.
## Configuration
Previously, we had defined a navigator like this:
```js
constSimpleApp=StackNavigator({
Home:{screen:HomeScreen},
Chat:{screen:ChatScreen},
});
```
We want paths like `chat/Taylor` to link to a "Chat" screen with the `user` passed as a param. Let's re-configure our chat screen with a `path` that tells the router what relative path to match against, and what params to extract. This path spec would be `chat/:user`.
```js
constSimpleApp=StackNavigator({
Home:{screen:HomeScreen},
Chat:{
screen:ChatScreen,
path:'chat/:user',
},
});
```
### URI Prefix
Next, let's configure our navigation container to extract the path from the app's incoming URI. When configuring a top-level navigator, we can provide `containerOptions`:
```js
constSimpleApp=StackNavigator({
...
},{
containerOptions:{
// on Android, the URI prefix typically contains a host in addition to scheme
In Xcode, open the project at `SimpleApp/ios/SimpleApp.xcodeproj`. Select the project in sidebar and navigate to the info tab. Scroll down to "URL Types" and add one. In the new URL type, set the identifier and the url scheme to your desired url scheme.

Now you can press play in Xcode, or re-build on the command line:
```sh
react-native run-ios
```
To test the URI in iOS, open safari and type `mychat://chat/Taylor`.
## Android
To configure the external linking in Android, you can create a new intent in the manifest.
In `SimpleApp/android/app/src/main/AndroidManifest.xml`, add the new `VIEW` type `intent-filter` inside the `MainActivity` entry:
In the previous example, we created a StackNavigator to display several screens in our app.
When navigating to a chat screen, we can specify params for the new route by providing them to the navigate function. In this case, we want to provide the name of the person on the chat screen:
The `user` param can be accessed from the chat screen:
```js
classChatScreenextendsReact.Component{
render(){
const{params}=this.props.navigation.state;
return<Text>Chatwith{params.user}</Text>;
}
}
```
### Setting the Header Title
Next, the header title can be configured to use the screen param:
```js
classChatScreenextendsReact.Component{
staticnavigationOptions={
// // Title may be a simple string:
// title: 'Hello',
// Or the title string may be a function of the navigation prop:
title:({state})=>`Chat with ${state.params.user}`
};
...
}
```
```phone-example
basic-header
```
### Adding a Right Button
Then we can add a [`header` navigation option](/docs/navigators/navigation-options#Stack-Navigation-Options) that allows us to add a custom right button:
```js
static navigationOptions = {
header: {
right: <Button title="Info" />,
},
...
```
```phone-example
header-button
```
Just like `title`, the `header` option can be defined as a function of the [navigation prop](/docs/navigators/navigation-prop). Let's render a different button based on the route params, and set up the button to call `navigation.setParams` when pressed.
```js
static navigationOptions = {
title: ({ state }) => {
if (state.params.mode === 'info') {
return `${state.params.user}'s Contact Info`;
}
return `Chat with ${state.params.user}`;
},
header: ({ state, setParams }) => {
// The navigation prop has functions like setParams, goBack, and navigate.
let right = (
<Button
title={`${state.params.user}'s info`}
onPress={() => setParams({ mode: 'info' })}
/>
);
if (state.params.mode === 'info') {
right = (
<Button
title="Done"
onPress={() => setParams({ mode: 'none' })}
/>
);
}
return { right };
},
...
```
Now, the header can interact with the screen route/state:
```phone-example
header-interaction
```
To see the rest of the header options, see the [navigation options document](/docs/navigators/navigation-options#Stack-Navigation-Options).
Let's use React Navigation to build a simple chat application for Android and iOS.
## Setup and Installation
First, make sure you're [all set up to use React Native](http://facebook.github.io/react-native/docs/getting-started.html). Next, create a new project and add `react-navigation`:
```sh
# Create a new React Native App
react-native init SimpleApp
cd SimpleApp
# Install the latest version of react-navigation from npm
npm install --save react-navigation
# Run the new app
react-native run-android # or:
react-native run-ios
```
Verify that you can successfully see the bare sample app run on iOS and/or Android:
```phone-example
bare-project
```
We want to share code on iOS and Android, so lets delete the contents of `index.ios.js` and `index.android.js` and replace it with `import './App';`.
Now lets create the new file for our app implementation, `App.js`.
## Introducing Stack Navigator
For our app, we want to use the `StackNavigator` because we want a conceptual 'stack' navigation, where each new screen is put on the top of the stack, and going back removes a screen from the top of the stack. Lets start with just one screen:
```js
import React from 'react';
import {
AppRegistry,
Text,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
The `title` of the screen is configurable on the [static `navigationOptions`](/docs/navigators/navigation-options), where many options can be set to configure the presentation of the screen in the navigator.
Now the same screen should appear on both iPhone and Android apps:
```phone-example
first-screen
```
## Adding a New Screen
Lets create a button in the `HomeScreen` component that links to our second page:
We're using the navigate function from the [screen navigation prop](/docs/navigators/navigation-prop). In addition to specifying the target `routeName`, we can also pass params that will be put into the new route.
Now let's create the Chat screen that displays the `name` param passed in through the route:
```js
class ChatScreen extends React.Component {
static navigationOptions = {
// Nav options can be defined as a function of the navigation prop:
title: ({ state }) => `Chat with ${state.params.user}`,
};
render() {
// The screen's current route is passed in to `props.navigation.state`:
const { params } = this.props.navigation.state;
return (
<View>
<Text>Chat with {params.user}</Text>
</View>
);
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});
```
Now you can navigate to your new screen, and go back:
It is common in mobile apps to compose various forms of navigation. The routers and navigators in React Navigation are composable, which allows you to define a complicated navigation structure for your app.
For our chat app, we want to put several tabs on the first screen, to view recent chat threads or all contacts.
## Introducing Tab Navigator
Lets create a new `TabNavigator` in our `App.js`:
```js
classRecentChatsScreenextendsReact.Component{
render(){
return<Text>Listofrecentchats</Text>
}
}
classAllContactsScreenextendsReact.Component{
render(){
return<Text>Listofallcontacts</Text>
}
}
constMainScreenNavigator=TabNavigator({
Recent:{screen:RecentChatsScreen},
All:{screen:AllContactsScreen},
});
```
If the `MainScreenNavigator` was rendered as the top-level navigator component, it would look like this:
```phone-example
simple-tabs
```
## Nesting a Navigator in a screen
We want these tabs to be visible in the first screen of the app, but new screens in the stack should cover the tabs.
Lets add our tabs navigator as a screen in our top-level `StackNavigator` that we set up in the [previous step](/docs/intro/).
```js
const SimpleApp = StackNavigator({
Home: { screen: MainScreenNavigator },
Chat: { screen: ChatScreen },
});
```
Because `MainScreenNavigator` is being used as a screen, we can give it `navigationOptions`:
```js
MainScreenNavigator.navigationOptions = {
title: 'My Chats',
};
```
Lets also add a button to each tab that links to a chat:
## Common React Navigation API - Hybrid Integration
This is a purely speculative API that demonstrates how it may be possible to integrate the [JS navigation API](./Common-Navigation-Spec.md) in a hybrid app.
## Setting up a screen
It should be possible to register new screens from JS into native. In your main bundle:
A HOC could be used to make this feel more elegant.
## Disabling/Enabling the right button
```
const TestScreen = ({ navigation }) => (
<View>
<Button onPress={() => navigation.dispatch({
type: 'ToggleMyButtonPressability',
})}>
{navigation.state.rightButtonEnabled ? 'Disable' : 'Enable'} right button
</Button>
<Text>Pressed {navigation.state} times</Text>
</View>
);
TestScreen.router = {
getStateForAction(action, lastState = {}) {
let state = lastState || {
rightButtonEnabled: true,
rightButtonTitle: 'Tap Me',
pressCount: 0,
};
if (action.type === 'ToggleMyButtonPressability') {
state = {
...state,
rightButtonEnabled: !state.rightButtonEnabled,
};
} else if (action.type === 'RightButtonPress') {
state = {
...state,
pressCount: state.pressCount + 1,
};
}
return state;
},
};
```
## Before JS starts
A JSON file could be defined for native to consume before JS spins up:
```
{
"screens": [
{
"type": "Profile",
"path": "/users/:id?name=:name",
"params": {
"name": "string",
"id": "number"
},
"title": "%name%' s Profile",
"rightButtonTitle": "Message %name%"
},
{
...
}
]
}
```
This seems like a pain to set up, so we can statically analyze our JS and autogenerate this JSON! If the JS in an app changes, there could be a way for JS to report the new routing configuration to native for use on the next cold start.
To handle your app's navigation state in redux, you can pass your own `navigation` prop to a navigator. Your navigation prop must provide the current state, as well as access to a dispatcher to handle navigation options.
With redux, your app's state is defined by a reducer. Each navigation router effectively has a reducer, called `getStateForAction`. The following is a minimal example of how you might use navigators within a redux application:
class AppWithNavigationState extends React.Component {
render() {
return (
<AppNavigator navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
})} />
);
}
}
const store = createStore(appReducer);
class App extends React.Component {
render() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
}
```
Now, your navigation state is stored with redux, and you can fire navigation actions using redux.
When a navigator is given a `navigation` prop, it relinquishes control of the state. So you are now responsible for persisting state, handling deep linking, integrating the back button, etc.
Each screen can configure several aspects about how it gets presented in parent navigators.
#### Two Ways to specify each option
**Static configuration:** Each navigation option can either be directly assigned:
```js
classMyScreenextendsReact.Component{
staticnavigationOptions={
title:'Great',
};
...
```
**Dynamic Configuration**
Or, each option can be a function that takes the following arguments, and returns the value of the option.
-`navigation` - the [navigation prop](/docs/navigators/navigation-prop) for the screen, with the screen's route at `navigation.state`
-`childRouter` - The child router, if the screen is a navigator
```js
classProfileScreenextendsReact.Component{
staticnavigationOptions={
title:(navigation,childRouter)=>{
returnnavigation.state.params.name+"'s Profile!";
},
};
...
```
#### Generic Navigation Options
The `title` navigation option is generic between every navigator. It is used to set the title string for a given screen.
```js
classMyScreenextendsReact.Component{
staticnavigationOptions={
title:'Great',
};
...
```
Unlike the other nav options which are only utilized by the navigator view, the title option can be used by the environment to update the title in the browser window or app switcher.
#### Default Navigation Options
It's very common to define `navigationOptions` on a screen, but sometimes it is useful to define `navigationOptions` on a navigator too.
Imagine the following scenario:
Your `TabNavigator` represents one of the screens in the app, and is nested within a top-level `StackNavigator`:
```
StackNavigator:
- route1: A screen
- route2: A TabNavigator
```
Now, when `route2` is active, you would like to hide the header. It's easy to hide the header for `route1`, and it should also be easy to do it for `route2`. This is what Default Navigation Options are for - they are simply `navigationOptions` set on a navigator:
```js
TabNavigator({
profile:ProfileScreen,
...
},{
navigationOptions:{
header:{
visible:false,
},
},
});
```
Note that you can still decide to **also** specify the `navigationOptions` on the screens at the leaf level - e.g. the `ProfileScreen` above. The `navigationOptions` from the screen will be merged key-by-key with the default options coming from the navigator. Whenever both the navigator and screen define the same option (e.g. `header`), the screen wins. Therefore, you could make the header visible again when `ProfileScreen` is active.
**Extending defaults:** In order to extend default config with screen-specific properties instead of overriding it, you configure an option like this:
```js
classProfileScreenextendsReact.Component{
staticnavigationOptions={
header:(navigation,defaultHeader)=>({
...defaultHeader,
visible:true,
color:'blue',
}),
}
...
}
```
The 2nd argument passed to the function are the default values for the `header` as defined on the navigator.
## Tab Navigation Options
```js
classTabScreenextendsReact.Component{
staticnavigationOptions={
tabBar:({state})=>({
label:'Tab Label',
icon:({tintColor})=>(
<Image
source={require('./tab-icon.png')}
style={[styles.icon,{tintColor:tintColor}]}
/>
),
visible:true
}),
};
};
```
-`label` - can be string or react component
-`icon` - function that returns icon component
-`visible` - true or false to show or hide the tab bar, if not set then defaults to true
Each screen in your app will recieve a navigation prop, which contains the following:
## `navigate` - Link to other screens
Call this to link to another screen in your app. Takes the following arguments:
-`routeName` - A destination routeName that has been registered somewhere in the app's router
-`params` - Params to merge into the destination route
-`action` - (advanced) The sub-action to run in the child router, if the screen is a navigator.
```js
classHomeScreenextendsReact.Component{
render(){
const{navigate}=this.props.navigation;
return(
<View>
<Text>Thisisthehomescreenoftheapp</Text>
<Button
onPress={()=>navigate('Profile',{name:'Brent'})}
title="Go to Brent's profile"
/>
</View>
)
}
}
```
## `state` - The screen's current state/route
A screen has access to its route via `this.props.navigation.state`. Each will contain:
-`routeName` - the name of the route config in the router
-`key` - a unique identifier used to sort routes
-`params` - an optional object of string options for this screen
```js
classProfileScreenextendsReact.Component{
render(){
const{state}=this.props.navigation;
// state.routeName === 'Profile'
return(
<Text>Name:{state.params.name}</Text>
);
}
}
```
## `setParams` - Make changes to route params
Firing the `setParams` action allows a screen to change the params in the route, which is useful for updating the header buttons and title.
```js
classProfileScreenextendsReact.Component{
render(){
const{setParams}=this.props.navigation;
return(
<Button
onPress={()=>setParams({name:'Lucy'})}
title="Set title name to 'Lucy'"
/>
)
}
}
```
## `goBack` - Close the active screen and move back
```js
classHomeScreenextendsReact.Component{
render(){
const{goBack}=this.props.navigation;
return(
<View>
<Button
onPress={()=>goBack()}
title="Go back from this HomeScreen"
/>
<Button
onPress={()=>goBack(null)}
title="Go back anywhere"
/>
<Button
onPress={()=>goBack('screen-123')}
title="Go back from screen-123"
/>
</View>
)
}
}
```
Optionally provide a key, which specifies the route to go back from. By default, goBack will close the route that it is called from. If the goal is to go back *anywhere*, without specifying what is getting closed, call `.goBack(null);`
## `dispatch` - Send an action to the router
Use dispatch to send any navigation action to the router. The other navigation functions use dispatch behind the scenes.
Note that if you want to dispatch react-navigation actions you should use the action creators provided in this library.
React Navigation routers work on web and allow you to share navigation logic with native apps. The views currently bundled in `react-navigation` currently only work on React Native, but that may change with future-facing projects like [react-primitives](https://github.com/lelandrichardson/react-primitives).
## Example App
[This website](https://reactnavigation.org/) is [built with](https://github.com/react-community/react-navigation/blob/master/website/) React Navigation, specifically using `createNavigator` and `TabRouter`.
See the source code of the site here: [App.js](https://github.com/react-community/react-navigation/blob/master/website/src/App.js).
To see how the app gets rendered on the server, see [Server.js](https://github.com/react-community/react-navigation/blob/master/website/src/Server.js). On the browser, the App wakes up and gets rendered with [BrowserAppContainer.js](https://github.com/react-community/react-navigation/blob/master/website/src/BrowserAppContainer.js).
## More Coming Soon
Soon this guide will be replaced with a more thorough walkthrough of react-navigation usage on the web.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.