Compare commits

...

488 Commits

Author SHA1 Message Date
Brent Vatne
d746a587b0 Release 2.11.2 2018-08-03 15:45:27 -07:00
Brent Vatne
dee03c839a Undo pathUtils rename 2018-08-03 15:33:38 -07:00
Brent Vatne
2104bf1a04 Release 2.11.1 2018-08-03 14:48:49 -07:00
Brent Vatne
4e2a409dca Fix a couple of exports and export a few more modules 2018-08-03 14:47:43 -07:00
Brent Vatne
51bfe8dd19 Release 2.11.0 2018-08-03 14:17:24 -07:00
Brent Vatne
04a4512c1b Export modules useful for moving stack navigator outside of core 2018-08-03 14:16:57 -07:00
Brent Vatne
4a5da86ce0 Release 2.10.0 2018-08-02 13:03:34 -07:00
Brent Vatne
a118122aed Update react-navigation-[tabs&drawer] 2018-08-02 13:02:01 -07:00
Justin Parker
a94f89ffe1 Fixes bug where null doesn't work in routerOptions paths object for deeplinking (#4791)
* 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.
2018-08-01 01:12:49 -07:00
Brent Vatne
9d77fd6d54 Add NavigationTestUtils and release 2.9.3 2018-07-26 15:49:34 -07:00
Brent Vatne
13cf4497ee Release 2.9.2 2018-07-25 11:52:39 -07:00
Tim Wang
9175118383 Export StackViewTransitionConfigs (#4761)
* export StackViewTransitionConfigs

* Add changelogs
2018-07-25 11:50:07 -07:00
Simone D'Avico
6fc21250ec Fix typo in header transition preset check (uitkit -> uikit) (#4757) 2018-07-25 11:49:24 -07:00
Yevhen
714d5eab6b Error when building with haul: ref to pathToRegexp.compile (#4658)
Error in source code that cause problem on react native using haul https://puu.sh/AT1uZ/158623d5a4.png
2018-07-25 20:28:05 +02:00
Brent Vatne
67233dc9ef Release 2.9.1 2018-07-24 10:49:56 -07:00
Brent Vatne
b0443c1861 Move more logs behind debug flag in stack playground 2018-07-24 10:47:59 -07:00
Brent Vatne
c0b637df52 Fix title offfset calculation 2018-07-24 10:47:02 -07:00
Brent Vatne
9a82706fba Fix snapshots 2018-07-20 14:44:26 -07:00
Brent Vatne
d973a26edb Release 2.9.0 2018-07-20 14:33:27 -07:00
Brent Vatne
852e7e1974 Respect custom background color in header wrapper 2018-07-20 14:30:38 -07:00
Brent Vatne
cd3707d64b Add headerLayoutPreset, add config for back button title visibility and make it have reasonable defaults, better back button ripple on Android (#4588) 2018-07-20 14:12:39 -07:00
Brent Vatne
3c36db455f Release 2.8.0 2018-07-19 15:48:09 -07:00
Brent Vatne
ec52c884c5 Update NavigationPlayground to Expo SDK 28 2018-07-19 15:46:24 -07:00
Brent Vatne
c4b3f25a0f Cleanup unused descriptors and handle the case where we might expect to have a descriptor but do not (#4723) 2018-07-19 13:16:38 -07:00
Eric Vicenti
93642e16e7 Fix createNavigator leak of old descriptors 2018-07-19 12:41:14 -07:00
Eric Vicenti
1a76556290 Fix leak in createNavigator
Previous descriptors had been retained because this binding caused `this.prevState` to remain referenced. This binds the component getter to null instead.
2018-07-19 12:21:22 -07:00
Reza Ghorbani
12b21f052e added header container styles to be customized (#4331) 2018-07-18 15:14:08 -07:00
Brent Vatne
c1f07dc167 Release 2.7.0 2018-07-17 15:50:18 -07:00
Brent Vatne
bc04b31d01 Add border for transparent header in example 2018-07-17 15:43:22 -07:00
Eric Vicenti
35307c70be Improve empty path and param handling (#4671)
* Overhaul Path handling

* Another test for deep link
2018-07-17 13:51:20 -07:00
Brent Vatne
7e3f4f3bec Fix tests 2018-07-17 13:49:12 -07:00
Brent Vatne
cbd0958e6f Remove unnecessary style array 2018-07-17 13:36:16 -07:00
Brent Vatne
cab4d71a5e Fix edge case where route was in nav state but never actually graduated to scene 2018-07-17 13:36:16 -07:00
Kenza Iraki
108ac0e2a9 Set borderBottom to transparent and of size 0 if headerTransparent is true (#4701) 2018-07-16 16:32:14 -07:00
Brent Vatne
fa4fdb9c57 Fix onTransitionStart config not being invoked with keyboard aware navigator, and use prop over config when available 2018-07-16 15:13:25 -07:00
Brent Vatne
ebdd2da79f Pull onTransitionStart from navigationConfig, fixes #4100 2018-07-16 14:55:34 -07:00
Matteo Codogno
1fe11c100e Fix #4608 - remove header left component only when a headerLeft optio… (#4679)
* Fix #4608 - remove header left component only when a headerLeft option is not specified

* Update CHANGELOG.md
2018-07-12 11:42:56 -07:00
Eric Vicenti
c4b84f1d66 Fix container referene to startup state data 2018-07-12 11:01:11 -07:00
Michael Lefkowitz
69f394be5b Feat/allow keyless replace (#4636)
* 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
2018-07-10 23:41:42 -07:00
Eric Vicenti
316e4991ac Add enableURLHandling to navigation container 2018-07-10 14:47:57 -07:00
Ashoat Tevosyan
805064cb5e [flow] Make NavigationRoute types exact (#4667)
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.
2018-07-10 13:59:09 -07:00
Dariusz Łuksza
8f199980cb Fix changelog (#4651)
Fixes 2.6.1 header link
2018-07-06 20:21:00 -07:00
Brent Vatne
37ca6a92ca Release 2.6.2 2018-07-06 10:44:30 -07:00
Brent Vatne
980e0409dc Temporarily remove warnings on vertical padding in header 2018-07-06 10:42:32 -07:00
Brent Vatne
a00ba5918a Default to 0 elevation on transparent header 2018-07-05 15:17:08 -07:00
Brent Vatne
ad6b25cff9 Fix 2.6.1 changelog 2018-07-05 15:07:17 -07:00
Brent Vatne
a69b67d6d2 Release 2.6.1 2018-07-05 15:03:14 -07:00
Brent Vatne
dc436e4d01 Warn for more invalid header styles 2018-07-05 15:02:48 -07:00
Brent Vatne
fe95bdeee6 Fix regression for shadow in header on Android 2018-07-05 14:53:41 -07:00
Brent Vatne
525528e38f Release 2.6.0 2018-07-04 13:04:00 -07:00
liuqiang1357
9f5f3d994c Fix bug: params not be passed to navigator inside SwitchNavigator (#4306) 2018-07-04 12:28:01 -07:00
Eric Vicenti
e8c1833053 Fix stack router child router delegation priority (#4635)
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.
2018-07-03 21:18:25 -07:00
Eric Vicenti
0921889f7a Avoid crash when calling isFocused on old route (#4634) 2018-07-03 12:03:54 -07:00
Sébastien Lorber
1951a3ac46 Add <NavigationEvents/> component (#4188)
* add NavigationEvents

* expose TabsWithNavigationEvents in lib entrypoints

* Add NavigationEvents example in playground

* Add NavigationEvents example in playground

* Add NavigationEvents tests

* Add NavigationEvents Flow declarations

* remove useless NavigationEvents constructor

* NavigationEvents => make tests more readable by avoiding beforeEach callback

* fix flow test error by adding <any, any> to React.Component
2018-06-29 07:34:11 -07:00
Eric Vicenti
4e384f8057 Routers: Deep Linking Overhaul (#4590)
* deep linking overhaul

* clean up PlatformHelpers

this had previously been required for old versions of react native and react-native-web
2018-06-29 07:27:12 -07:00
Eric Vicenti
3d06d19d6a clean up PlatformHelpers (#4586)
this had previously been required for old versions of react native and react-native-web
2018-06-28 10:02:52 -07:00
Brent Vatne
30ef5ef72b Release 2.5.5 2018-06-27 18:12:59 -07:00
Brent Vatne
c7fff52408 Delegate to child routers for more than just the top screen in the stack (#4587)
* Delegate to child routers for more than just the top screen in the stack. Fixes #4185

* Add CHANGELOG entry
2018-06-27 17:37:30 -07:00
Brent Vatne
bc01a4cd57 Throw error in development mode when title is not a string 2018-06-27 17:35:29 -07:00
Brent Vatne
cad3d70aed Update react-navigation-drawer to 0.4.3 2018-06-27 17:27:58 -07:00
Brent Vatne
bb5719f438 Throw an error when header is invalid 2018-06-27 17:22:00 -07:00
Brent Vatne
3dd3f5b804 Release 2.5.4 2018-06-27 15:24:34 -07:00
Julian Paas
3d8d5a0634 Adds getNavigation to web exports (#4551) 2018-06-27 13:34:45 -07:00
Brent Vatne
54448ed070 Prevent flicker in header when header is null on initial mount (when using default header sizes) (#4577)
* Prevent flicker in header in most common cases. Fixes https://github.com/react-navigation/react-navigation/issues/4264

* Update snapshots
2018-06-26 13:27:43 -07:00
Julian Paas
369ac2b568 Adds SwitchNavigator to react-navigation-web (#4550)
* Adds SwitchNavigator to react-navigation-web
2018-06-26 11:24:23 -07:00
Vojtech Novak
3dc592f679 Update ISSUE_TEMPLATE.md (#4575) 2018-06-25 15:41:56 -07:00
Brent Vatne
4f93200c91 Release 2.5.3 2018-06-25 14:37:26 -07:00
Brent Vatne
665736d754 Hoist navigation action creators for router above those for child router 2018-06-25 14:33:01 -07:00
Brent Vatne
5598c3e28f Update changelog 2018-06-23 11:03:38 -07:00
Brent Vatne
cde6e845cd Release 2.5.2 2018-06-23 11:02:14 -07:00
Brent Vatne
fb8c712ad8 Update react-navigation-drawer to 0.4.2 to fix toggle regression 2018-06-23 11:01:47 -07:00
Brent Vatne
350b7e0aed Release 2.5.1 2018-06-22 13:21:22 -07:00
Brent Vatne
de112565d3 Fix name of prop, should be lastTransitionProps instead of prevTransitionProps in StackViewLayout
- Fixes #4542
2018-06-22 13:18:26 -07:00
Brent Vatne
acdd515c13 Update example app.json 2018-06-22 12:50:50 -07:00
Rodrigo Bermúdez Schettino
452a6d2004 Improve changelog format (#4559)
Bug fixes should be listed in the "Fixed" section instead of "Changed" according to keepachangelog.
2018-06-22 10:41:58 -07:00
Brent Vatne
08c8031a71 Release 2.5.0 2018-06-22 10:32:11 -07:00
Eric Vicenti
608365266a @ericvicenti/universe (#4493)
* 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
2018-06-22 10:20:27 -07:00
Rodrigo Bermúdez Schettino
247fba56e6 Fix typo in Pull Request Template (#4558)
Also link to the "Unreleased" section in CHANGELOG.
2018-06-22 10:19:41 -07:00
Brent Vatne
060f5dcecf Update PR template for changelog 2018-06-22 08:25:38 -07:00
Rodrigo Bermúdez Schettino
fdec05c87a Create CHANGELOG.md (#4544)
List all changes between versions to notify about notable changes in releases.
2018-06-22 08:22:15 -07:00
Brent Vatne
76da804574 Fixes #4491 2018-06-21 15:24:52 -07:00
Brent Vatne
dde091848a Release 2.4.1 2018-06-20 15:35:07 -07:00
Brent Vatne
824fa32416 Improve playground on Android 2018-06-20 14:20:00 -07:00
Brent Vatne
c518e7f36c Improve example 2018-06-20 13:51:34 -07:00
Brent Vatne
1cfe01dbdb Release 2.4.0 2018-06-20 13:38:05 -07:00
Brent Vatne
e62a9050fd Fix withDefaultValue 2018-06-20 13:37:33 -07:00
Christophe Hurpeau
310b909ba8 createNavigationContainer: rethrow the error instead of creating a new one (#4533)
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 ?
2018-06-20 13:03:02 -07:00
Eric Vicenti
aebe8a5c23 Fix isTransitioning on nested navigate (#4520)
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
2018-06-20 12:17:14 -07:00
Vladislav Shabanov
e1df2c6c4a Make headers of non-standard heights work correctly in StackNavigator when header is null (Fixes #4208) (#4353)
* Measure header height dynamically

* Add comment

* StacksOverTopTabs playground example
2018-06-15 08:10:43 -07:00
Ashoat Tevosyan
fa86718a24 Revert "Export getNavigationActionCreators (#4258)" (#4495)
This reverts commit 1e7d8d55c3.
2018-06-14 11:34:38 -07:00
Ashoat Tevosyan
c8e5673183 [flow] Type getNavigation (#4505)
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.
2018-06-14 11:33:50 -07:00
Ashoat Tevosyan
b312a5e307 [ReduxExample] Update to use react-navigation-redux-helpers@2.0.0 (#4504) 2018-06-14 11:15:11 -07:00
Brent Vatne
ee6a6c53b1 Fix incorrect methods being called in createKeyboardAwareNavigator 2018-06-13 14:50:03 -07:00
Eric Vicenti
8edec88341 Export getNavigation as public API, test redux (#4489)
This unblocks the fixing of react-navigation-redux-helpers to unbreak redux support in 2.3

https://github.com/react-navigation/react-navigation-redux-helpers/pull/37

All redux users will need to change their code to reflect the changes made here to `ReduxExample/AppNavigator`
2018-06-12 11:59:09 -07:00
Brent Vatne
b8d6d4253d Release 2.3.1 2018-06-12 11:32:08 -07:00
Eric Vicenti
0adb1ba9f1 Export getNavigation as public API, test redux (#4488)
This unblocks the fixing of react-navigation-redux-helpers to unbreak redux support in 2.3

https://github.com/react-navigation/react-navigation-redux-helpers/pull/37

All redux users will need to change their code to reflect the changes made here to `ReduxExample/AppNavigator`
2018-06-12 11:30:23 -07:00
Brent Vatne
d3ef3d1271 Release 2.3.0 2018-06-11 15:54:41 -07:00
k-murakami0609
89a24bdc12 fix broken link to Common mistakes (#4468) 2018-06-10 10:41:18 -07:00
Brent Vatne
128a95b496 Release 2.3.0-beta.1 2018-06-09 14:18:09 -07:00
Brent Vatne
470eaf3b08 Make the actions available on the navigator navigation prop the same as its children (#4467)
* Make the actions available on the navigator navigation prop the same as its children

* Fix test and improve code clarity
2018-06-09 14:13:21 -07:00
Brent Vatne
c91e8206a5 Fix ScenesReducer test 2018-06-08 17:44:32 -07:00
Brent Vatne
da283915f8 Release 2.3.0-beta.0 2018-06-08 17:36:42 -07:00
Brent Vatne
3031e7bd80 Update header when screenProps change (Fixes #4271) 2018-06-08 17:35:17 -07:00
Brent Vatne
98a4f26f26 Bump react-navigation-drawer. Fixes #4416 2018-06-08 16:27:36 -07:00
Brent Vatne
b7f5435c93 Fix withNavigation in non-floating headers 2018-06-08 15:48:21 -07:00
Brent Vatne
21ef4fcb82 Return result of dispatch from action helpers 2018-06-08 14:33:01 -07:00
Eric Vicenti
5f64a2a9cb Refactor redo, child navigation to navigation prop (#4453) 2018-06-08 14:20:07 -07:00
Brent Vatne
992d0fb267 Release 2.2.5 2018-06-08 09:40:39 -07:00
ensecoz
6f41379ed1 extract correct property for onTransitionEnd (#4459) 2018-06-08 09:35:36 -07:00
Tom Klaver
267af01e72 throw readable error when wrong navigation prop is passed (#4455)
* add warning when passing wrong navigation prop: https://github.com/react-navigation/react-navigation/issues/3598

* add test for throwing when passing wrong navigation prop

* wrong nav prop error: update snapshots, throw => throw new, update docs reference url
2018-06-08 09:31:05 -07:00
Arthur Levoyer
b68c3a755d Add missing tests about DeepLinking (#4451)
* Fix #1950 (Deep link not working when nesting have more than two levels.)

* Fix test
2018-06-07 11:37:57 -07:00
Brent Vatne
7345634493 Release 2.2.4 2018-06-07 11:33:14 -07:00
Brent Vatne
6517169119 Re-compute options when screenProps change 2018-06-07 11:31:31 -07:00
Brent Vatne
ea5d14a720 Release 2.2.3 2018-06-06 21:13:00 -07:00
Brent Vatne
313d0726a8 Add some logs to NavigationPlayground around helper dispatch return value
This is a poor substitute for tests
2018-06-06 21:12:18 -07:00
Brent Vatne
b52f153747 Return the result of dispatch from helpers. Fixes #4445 2018-06-06 21:01:51 -07:00
Brent Vatne
44621005ff Release 2.2.2 2018-06-06 14:34:59 -07:00
Brent Vatne
bf58364c3d Bump react-navigation-drawer 2018-06-06 14:34:42 -07:00
Brent Vatne
b55053cde6 Release 2.2.1 2018-06-06 13:24:50 -07:00
Brent Vatne
9abb2644a9 Bump react-navigation-tabs and rebuild yarn.lock 2018-06-06 13:24:29 -07:00
Brent Vatne
6a946d6ab7 Revert "Refactor, move child navigation to navigation prop (#4425)"
This reverts commit ba62509ff4.
2018-06-06 13:19:08 -07:00
陈然
395abe5200 Change 'React' import writing, Prevent warnings in old version React (#4428) 2018-06-06 12:51:09 -07:00
Eric Vicenti
ba62509ff4 Refactor, move child navigation to navigation prop (#4425)
* 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
2018-06-06 12:50:30 -07:00
Brent Vatne
45391db7d9 Move all drawer code into react-navigation-drawer (#4435)
* Move all drawer code into react-navigation-drawer

* Remove react-native-drawer-layout-polyfill from package.json
2018-06-06 12:11:28 -07:00
Brent Vatne
7f86362e86 Release 2.2.0 2018-06-05 12:21:09 -07:00
Brent Vatne
99605737e9 Bump react-navigation-tabs to latest 2018-06-05 12:20:47 -07:00
Serge Lebedev
842f5eb7b2 [flow] Fix NavigationScreenComponent's navigationOptions (#4317) 2018-06-05 12:19:12 -07:00
Richárd Biró
183ea82416 Pass getCustomActionCreators to Drawer route (#4433) 2018-06-05 11:12:03 -07:00
Rodrigo Bermúdez Schettino
108a6504a7 Use consistent naming in README (#4427)
Use the same casing (camel case) as in the README's title for the License section.
2018-06-05 10:55:20 -07:00
Eric Vicenti
f92d671746 Fix getCustomActionCreators in drawer navigator 2018-06-05 10:51:05 -07:00
Brent Vatne
e0c4a8f7d3 Release 2.1.0 2018-06-04 14:04:00 -07:00
Rodrigo Bermúdez Schettino
bc881c8aa1 Update deprecated StackNavigator usage (#4389)
Use createStackNavigator instead.
2018-06-04 13:59:55 -07:00
Ashoat Tevosyan
118c19dcce [flow] Update NavigationActions and introduce StackActions and DrawerActions (#4345) 2018-06-04 13:58:14 -07:00
James Bechet
01b43974e6 fix swipe to go back by providing the index (#4409) 2018-06-04 13:55:26 -07:00
Brent Vatne
2f90899620 Cache descriptors in createNavigator (#4424) 2018-06-04 13:54:09 -07:00
Eric Vicenti
6cc86f66e1 Fix stack router state change without isTransitioning change (#4368) 2018-06-04 12:47:40 -07:00
Eric Vicenti
4be99b6645 Transitioner: Fix instantaneous transitions (#4404)
* 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
2018-06-04 12:46:08 -07:00
Eric Vicenti
80016b7218 Fix race condition in DrawerView (#4392) 2018-06-03 13:35:55 -07:00
Eric Vicenti
f555a9ec9a Fix drawer router logic to close drawer (#4394) 2018-06-03 13:35:30 -07:00
Brent Vatne
05cbd85d5c Temporarily stop running flow on navigation playground due to internal react-native flow errors 2018-06-01 15:02:12 -07:00
Hunkyo Jung
51965eac38 Pass getCustomActionCreators to StackRouter (#4366) 2018-05-31 19:21:11 -07:00
Brent Vatne
a3956bf3ce Update tab snapshots 2018-05-31 13:53:00 -07:00
Brent Vatne
ce24c66b5a Disable react/no-deprecated to pass CI without breaking old versions of React 2018-05-31 13:47:28 -07:00
Brent Vatne
5467f0e22d Release 2.0.4 2018-05-25 23:05:54 -07:00
Ashoat Tevosyan
1e7d8d55c3 Export getNavigationActionCreators (#4258)
* 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
2018-05-25 22:59:11 -07:00
Brent Vatne
1d2ce862c2 Fix Stacks over Tabs example 2018-05-25 16:07:55 -07:00
Louis Lagrange
d778479e4a Fix drawer router initial state (#4219)
* Fix drawer router initial state

* Add test

* Be concise
2018-05-25 16:01:53 -07:00
Sébastien BARBIER
352dae50e1 Apply drawerlockmode from screen options to DrawerLayout component (#4202)
Fix #4201
2018-05-25 15:50:39 -07:00
Louis Lagrange
61385cae59 Export missing Drawer components (#4221) 2018-05-25 15:49:33 -07:00
Brent Vatne
aa3c13891e Bump some versions 2018-05-25 15:26:25 -07:00
Andrei Xavier de Oliveira Calazans
9696d7220d fix(create-nav-container): pass up error on catch (#4298) 2018-05-25 15:13:18 -07:00
Louis Lagrange
2b83b44816 Remove obsolete DrawerScreen (#4222) 2018-05-25 14:45:45 -07:00
Louis Lagrange
ec749023ed [Web] Fix header height margin (#4206) 2018-05-25 14:44:46 -07:00
Sébastien Lorber
adc9389eb3 Add CircleCI Badge to README (#4318)
Displaying a badge is helpful for users but also contributors (for example to know why my upstream-rebased PR is not passing tests)
2018-05-25 14:41:27 -07:00
Sébastien Lorber
54d143fee2 Fix Codecov link -> react-community vs react-navigation (#4319) 2018-05-25 14:39:51 -07:00
Louis Lagrange
d50e74d0c7 Fix NavigatorContainer test (fixes CI) (#4327) 2018-05-24 17:43:58 +02:00
Nicolas Charpentier
22926c5230 Optimize images (#4251) 2018-05-23 16:54:23 -07:00
Ashoat Tevosyan
f6c47a6c66 [examples] Update ReduxExample (#4267)
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.
2018-05-23 10:20:14 -07:00
Ashoat Tevosyan
046a9f8930 [flow] Make StackRouter action creators optional and add DrawerRouter ones (#4257)
This will force all Flow users to do runtime assertions if they want to use these action creators. Open to any better solutions.
2018-05-23 10:18:35 -07:00
Ashoat Tevosyan
72f17538c2 [flow] Fix tabBarOnPress type for react-navigation@2.0 (#4256) 2018-05-23 10:18:11 -07:00
Ashoat Tevosyan
550001b053 [flow] Fixes for v2 libdef (#4230)
* [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
2018-05-23 10:17:45 -07:00
Brent Vatne
d168ab26f9 Release 2.0.2 2018-05-21 17:56:24 -07:00
Brent Vatne
99916328a1 Don't warn about multiple navigation containers on Android
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.
2018-05-21 17:55:05 -07:00
Eric Vicenti
08e1b53f2e Update playground yarn lockfile 2018-05-12 10:48:45 -07:00
Eric Vicenti
2243528e97 Cache panResponder in StackView (#4183)
* fix swipe gesture bug

* panresponder as instance prop
2018-05-09 17:36:57 -07:00
Steven Kabbes
931271198b Remove unused code addNavigationHelpers (#4179) 2018-05-09 14:53:06 -07:00
Brent Vatne
1876706bad Release 2.0.1 2018-05-08 17:45:02 -07:00
Eric Vicenti
e97d6b26a8 Fix dispatch implementation (#4168)
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
2018-05-08 17:41:08 -07:00
Brent Vatne
ec1694f909 Release 2.0.0 2018-05-07 13:47:13 -07:00
Brent Vatne
93db7d0c95 Release 2.0.0-rc.14 2018-05-07 13:03:21 -07:00
Brent Vatne
589b80b2fa Update drawer example 2018-05-07 13:01:22 -07:00
Eric Vicenti
364144d639 Navigation Action Helpers at root (#4151) 2018-05-07 12:56:35 -07:00
Brent Vatne
2fd7284fe2 Release candidate lucky number 13 2018-05-07 11:54:50 -07:00
Brent Vatne
6499f02157 Only blur input when index changes on transition start (Fixes #4148) 2018-05-07 11:47:56 -07:00
Brent Vatne
39d5714ac0 Release 2.0.0-rc.12 2018-05-07 11:14:03 -07:00
Brent Vatne
1ceda5f04d Update react-navigation-deprecated-tab-navigator. Closes #4147 2018-05-07 11:13:34 -07:00
Brent Vatne
4533883ba7 Release 2.0.0-rc.11 2018-05-06 13:41:53 -07:00
spaceye
8ec2466fef Fix for broken swipe back gesture in RTL mode (#4119)
* 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.
2018-05-06 12:42:22 -07:00
Brent Vatne
1bd6593ede Release 2.0.0-rc.10 2018-05-06 12:00:02 -07:00
Eric Vicenti
4e8d8ce12f Fixes to drawer router handling of child routers (#4131)
Addresses #4129, and also lets child routers swallow actions with null. Tests added
2018-05-06 11:59:40 -07:00
Eric Vicenti
9f95a7f10b Fix CompletionAction trigger (#4115) 2018-05-06 11:57:51 -07:00
Serge Lebedev
f6bd3e4306 Fix setting undefined value to isTransitioning (#4124) 2018-05-06 10:04:57 -07:00
Eric Vicenti
c1a94895f5 Fix drawer stack reset-to-top behavior (#4132)
“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.
2018-05-06 09:51:18 -07:00
Brent Vatne
ad7cde9eb9 Release 2.0.0-rc.9 2018-05-04 11:16:34 -07:00
Brent Vatne
2643f690a9 Pull createMaterialBottomTabNavigator into separate repo 2018-05-04 11:06:51 -07:00
Brent Vatne
8e52995ef3 Release 2.0.0-rc.8 2018-05-04 10:14:34 -07:00
Eric Vicenti
8ed3817c90 Fix event unsubscription logic (#4116)
Events were getting unsubscribed too early, so that the inner willBlur event was getting skipped when trying to “dismiss” a deep navigation stack.
2018-05-04 10:14:22 -07:00
Brent Vatne
eda9bfd567 Update react-lifecycles-compat 2018-05-04 10:10:28 -07:00
Eric Vicenti
723c5f2149 Fix drawer navigation dispatch (#4121) 2018-05-04 09:48:45 -07:00
Brent Vatne
ab5481a290 Add context around a test in switchrouter 2018-05-03 15:43:37 -07:00
Brent Vatne
df281cfed0 Add router tests to clarify route resolution 2018-05-03 15:42:23 -07:00
Eric Vicenti
e0df3cf74a Fix issue with nested navigation actions in stack (#4114) 2018-05-03 10:13:43 -07:00
Vojtech Novak
2440af66e4 add a test so that #2856 can be closed (#4102)
* add test for 2856

* rename variables
2018-05-02 20:02:03 -07:00
simonbuerger
47fe858d4e StateUtils: Use Array.prototype.findIndex instead of map => indexOf (#4106)
* 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
2018-05-02 20:01:20 -07:00
Eric Vicenti
c641bee11b Fix initial action dispatch for nonPersisted apps (#4104) 2018-05-02 09:17:00 -07:00
Brent Vatne
4b39e2db3c Release 2.0.0-rc.7 2018-04-30 17:08:23 -07:00
Eric Vicenti
f7533a790f Add tests to confirm setParam behavior (#4099)
Adding these tests because reports from this issue make me nervous:

https://github.com/react-navigation/react-navigation/issues/1274
2018-04-30 16:37:41 -07:00
Brent Vatne
c56122466f Release 2.0.0-rc.6 2018-04-30 16:19:28 -07:00
Brent Vatne
7fc992dc58 Container state can be out of date if we have async functions between getting it and using it (#4098) 2018-04-30 15:59:49 -07:00
Rob Allsopp
32922cdd7d go back to React$, and fix real error (#4095) 2018-04-30 12:04:48 -07:00
Rob Allsopp
eda51b3b79 Fix missing/incorrect flow types (#4085)
* don’t use private global

* add missing method ‘getParam’ to navigation screen prop

* correct return type for ‘withNavigation’

* add usage of `getParam` method
2018-04-27 14:30:23 -07:00
Jed Mao
921ee09587 Fix "npm test" on Windows 10 (#4066)
* Fix Windows

* update prettier

* Explain need for assetsTransformer in comment
2018-04-27 08:57:07 -07:00
Brent Vatne
7ae4c60eb8 Release 2.0.0-rc.5 2018-04-25 17:49:17 -07:00
Brent Vatne
5fff7ef5c6 Give inactive routes in stack opportunity to handle action (#4064) 2018-04-26 00:48:55 +00:00
Brent Vatne
42bb1cc317 Release 2.0.0-rc.4 2018-04-25 17:04:15 -07:00
Brent Vatne
337fd89ad5 Bump react-navigation-deprecated-tab-navigator 2018-04-25 16:57:42 -07:00
Brent Vatne
acf9b92ff7 Bump react-navigation-tabs 2018-04-25 16:49:57 -07:00
Rich Gilbank
5072130d6f Typo in deprecation notice (#4051) 2018-04-24 11:10:48 -07:00
Brent Vatne
20bbbd62ff Release 2.0.0-rc.3 2018-04-20 17:40:02 +03:00
Adam Miskiewicz
0890896824 Make StackNavigator keyboard aware (#3951)
* 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
2018-04-20 17:03:25 +03:00
Serhii Palash
0cf14f8e1e Fix TabNavigator export ( Issue #3962 ) (#3979) 2018-04-20 16:40:18 +03:00
Brent Vatne
e5e434c9e2 Fix _isRouteFocused so it takes a route and returns bool rather than fn 2018-04-20 16:39:03 +03:00
Janic Duplessis
e5d8d2c216 Fix header hardcoded height to accound for iPhone X and orientation changes (#4017) 2018-04-20 16:34:33 +03:00
Eric Vicenti
abd5200739 Fix header ModularLeftComponent to goBack from child navigation (#4023) 2018-04-20 16:33:36 +03:00
Brent Vatne
202609d9cf Release 2.0.0-rc.2 2018-04-09 17:26:32 -07:00
Yao Hui Chua
7b4dd98255 Shift tests to isolate routers (#3876) 2018-04-09 13:00:01 -07:00
Janic Duplessis
70c644f522 Fix transition between 2 screens with no header (#3939) 2018-04-09 12:32:27 -07:00
Janic Duplessis
5274d16e3b Use Header.HEIGHT instead of measuring to avoid flicker (#3940) 2018-04-09 12:31:43 -07:00
Janic Duplessis
e5e2cbb86d Fix header transition when mode is set to screen (#3927) 2018-04-09 11:22:51 -07:00
Brent Vatne
a8caa0d93c Release 2.0.0-rc.1 2018-04-06 15:14:32 -07:00
Eric Vicenti
f70a25a6a8 drawer router key (#3925) 2018-04-06 15:13:55 -07:00
emision
6cde6e2558 add isFocused helper definition (#3912) 2018-04-06 12:43:51 -07:00
Brent Vatne
0794c0faaa Fix typo in SwitchRouter 2018-04-06 12:42:42 -07:00
Brent Vatne
ea28e84e5a Fix stackConfig typo 2018-04-06 12:39:44 -07:00
Eric Vicenti
419ee5318d custom action creators api (#3923) 2018-04-06 12:12:39 -07:00
Brent Vatne
fbbf00875b Release 2.0.0-beta.10 2018-04-05 14:46:33 -07:00
Brent Vatne
22e09f7186 Prevent double application of navigationOptions function when using RouteName: ScreenName route config 2018-04-05 14:45:41 -07:00
Brent Vatne
ece6297e8e Release 2.0.0-beta.9 2018-04-05 12:09:55 -07:00
Eric Vicenti
ad52caf57b Immediate transition fix, avoid stale render (#3901) 2018-04-05 11:35:16 -07:00
Eric Vicenti
11f5e6e8e5 container initialization fix (#3899) 2018-04-05 11:29:59 -07:00
Eric Vicenti
1764b21f34 fix header back (#3900) 2018-04-05 11:29:15 -07:00
Eric Vicenti
bbacabeba3 avoid unnecessary navigation completion dispatches (#3902) 2018-04-05 11:27:32 -07:00
Eric Vicenti
b140b70555 no more component will mount (#3903) 2018-04-05 11:25:26 -07:00
Eric Vicenti
356646cbfa Enhance replace action creator (#3906) 2018-04-05 11:25:04 -07:00
Brent Vatne
6234b5661e Release 2.0.0-beta.8 2018-04-04 19:34:09 -07:00
Brent Vatne
270c3f0754 Bump react-navigation-tabs dependency 2018-04-04 19:33:51 -07:00
Brent Vatne
6f04bdffa6 Update NavigationPlayground dependencies 2018-04-04 19:33:01 -07:00
Brent Vatne
8415378784 Release 2.0.0-beta.7 2018-04-04 18:37:41 -07:00
Brent Vatne
9e47092d56 Fix isFocused and example 2018-04-04 18:37:08 -07:00
Brent Vatne
029d6ac4d2 Update react-navigation-tabs 2018-04-04 18:17:57 -07:00
Gaëtan Renaudeau
d57d118fda Update Flowtype to support navigation.navigate({}) (#3843) 2018-03-26 17:17:36 -04:00
Brent Vatne
2232e394bb Fix refactoring errors 2018-03-25 19:04:15 -07:00
Eric Vicenti
670d48366b Actions creators overhaul (#3619) 2018-03-25 18:31:59 -07:00
Brent Vatne
99ac5b6c08 Release 2.0.0-beta.6 2018-03-25 12:33:30 -07:00
Brent Vatne
68a2a106f3 Warn when users have multiple stateful navigation containers (#3819)
* First pass at warning when users explicitly render nested navigators

* Clean up tests around warnings

* Update comment

* Update comment again
2018-03-25 12:33:11 -07:00
Gianfrancø Palumbo
b7c6d072a5 fix(redux example readme): link to doc (#3828) 2018-03-25 10:49:22 -07:00
Eric Vicenti
ecd9fd71e9 withNavigation improvement (#3834)
The navigation prop should also pass through, and be prioritized over context because it is more explicit

This also fixes an incorrect warning/invariant
2018-03-25 10:49:09 -07:00
Adam Miskiewicz
cfc9690326 Smoothly transition header visibility in Stack
This closes #2732 (which also happens to be the top issue on canny.io).
2018-03-25 10:27:59 -07:00
Adam Miskiewicz
828e7f2d43 Update react-native-scripts in NavigationPlayground (#3820)
We were pretty far behind in react-native-script versions for the playground, so I updated them.

Test Plan:

Run `yarn`.
2018-03-23 12:25:53 -07:00
Tom Klaver
9c3fffa47f Fix broken link behind PRs Welcome badge (#3824) 2018-03-23 11:23:10 -04:00
Brent Vatne
be524e4224 Release 2.0.0-beta.5
- Update react-navigation-tabs
2018-03-22 20:52:47 -07:00
Brent Vatne
095814230b Release 2.0.0-beta.4 2018-03-22 19:43:47 -07:00
Eric Vicenti
9cf557bba0 State persistence (#3716)
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.
2018-03-22 22:42:37 -04:00
Eric Vicenti
5e4512f3eb Implement paths on SwitchRouter (#3806)
* Fix paths overriding in SwitchRouter
2018-03-22 22:41:27 -04:00
Brent Vatne
ee1b5972ce Release 2.0.0-beta.3 2018-03-19 16:53:34 -04:00
Brent Vatne
2233d0e1d8 Add switch example 2018-03-19 16:52:12 -04:00
Eric Vicenti
577d99c165 StackRouter to return null on idempotent navigation (#3793)
This new behavior indicates that the action has been handled, but the state has not changed.
2018-03-19 16:46:57 -04:00
Brent Vatne
aa362ea776 Release 2.0.0-beta.2 2018-03-19 13:06:49 -04:00
Brent Vatne
864908a49c Bump version to 2.0.0-beta.1 2018-03-19 01:36:37 -04:00
Brent Vatne
5cab55b8c9 Release 2.0.0-beta.0 2018-03-19 00:13:27 -04:00
Brent Vatne
9b9db86bde Release 2.0.7 2018-03-18 22:22:26 -04:00
Eric Vicenti
4def39c0f7 Improve path matching for SwitchRouter and empty paths (#3784) 2018-03-18 22:10:15 -04:00
Brent Vatne
e6559f5878 Add react-native-tabs as export from react-navigation 2018-03-18 17:50:02 -04:00
Eric Vicenti
a9d8f2e03e Temporarily disable broken test in NavigationPlayground 2018-03-18 12:22:56 -04:00
Brent Vatne
84a070b9d5 Release 2.0.0-alpha.6 2018-03-17 16:27:52 -04:00
Brent Vatne
ee984943c7 Fix push action -- regressed when making navigate "less pushy" 2018-03-17 16:27:19 -04:00
Brent Vatne
9fdfec18f6 Remove yarn link in test script 2018-03-16 20:08:47 -04:00
Eric Vicenti
aee16b91a4 Improve consistency of jest version
Hopefully will fix build on Circle
2018-03-16 16:21:17 -07:00
Jakob Murko
191439f79a Prevent duplicate drawer events (#3763) 2018-03-16 15:36:31 -07:00
Brent Vatne
b1ac152fec Rename 'carefullyGetParent' to 'dangerouslyGetParent'
- 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 ;)
2018-03-15 16:01:58 -07:00
Brent Vatne
c588ab9f9d Fix TabNavigator related tests 2018-03-15 13:40:29 -07:00
Brent Vatne
ae8cd41396 Deprecate TabNavigator in favor of react-navigation-tabs 2018-03-15 13:31:41 -07:00
Michał Pierzchała
5038ee2360 Fix memory leak in TabView-test.js (#3742) 2018-03-15 12:25:08 -07:00
Brent Vatne
5bf071e3ee Release 2.0.0-alpha.5 2018-03-15 10:57:33 -07:00
Michał Pierzchała
fcbf78e658 feat(context): refactor passing navigation context (#3668)
* feat(context): refactor passing navigation context

* remove commented code in example

* adjust src/views/withNavigationFocus.js

* refactor stuff

* extract scene to variable

* Add test

* Apply CR comments

* remove junk

* bring back screen mode header
2018-03-15 10:55:00 -07:00
KUBO
fd75e9c14c Remove unuseful SafeAreaView (#3721) 2018-03-15 10:35:02 -07:00
Brent Vatne
7d36a3b137 Update snapshots 2018-03-15 10:34:18 -07:00
Brent Vatne
175387b22f Another fix for frustrating tab bar icon layout issue 2018-03-15 10:34:18 -07:00
Brent Vatne
0dd7daecc0 Rename exports for navigators from XNavigator to createXNavigator (#3753) 2018-03-14 23:23:04 -07:00
Brent Vatne
42230634fd Missed a case where we should not have flexGrow 2018-03-14 21:48:48 -07:00
Brent Vatne
a9943e9b2e Update snapshot 2018-03-14 21:42:39 -07:00
Brent Vatne
6475e32dba Apply horizontal icon style whenever we should use horizontal tabs in icon 2018-03-14 21:34:53 -07:00
Brent Vatne
f67872d8f1 Release 2.0.0-alpha.4 2018-03-14 15:22:14 -07:00
Brent Vatne
2c7187b22a Rename exports for navigators from XNavigator to createXNavigator 2018-03-14 15:21:38 -07:00
Brent Vatne
160d44f58e Fix back button on modular header 2018-03-14 15:19:03 -07:00
spaceye
d017ed01b3 Reworked headerBackImage navigation prop and rendering (#3680)
* 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.
2018-03-13 13:15:11 -07:00
Vojtech Novak
c2e197f8d3 fix contribution docs link (#3707) 2018-03-13 13:14:02 -07:00
Vojtech Novak
6b3968b601 Playground facelift (#3708)
* wip

* fix imports

* use stylesheet for margin

stylesheet now correct

* also remove old headerLeft

* improve header buttons color

* remove ios button margin
2018-03-13 13:13:19 -07:00
Vojtech Novak
b575200879 reuse styles (#3725) 2018-03-13 13:05:21 -07:00
Brent Vatne
cd5bd8882e Release 2.0.0-alpha.3 2018-03-12 16:19:48 -07:00
Brent Vatne
3f837c895e Add lifecycle polyfill and change away from componentWillMount where possible without too much refactoring 2018-03-12 16:05:43 -07:00
Brent Vatne
bc5d35aba3 Release 2.0.0-alpha.2 2018-03-12 16:01:57 -07:00
Brent Vatne
9a6e0bbd98 Add dismiss helper, made possible by also adding carefullyGetParent (#3669)
* 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
2018-03-12 16:01:29 -07:00
Brent Vatne
052d22804c Release 2.0.0-alpha.1 2018-03-12 15:23:38 -07:00
Brent Vatne
7a978b1087 Implement "less pushy navigate" RFC 2018-03-12 15:22:51 -07:00
Brent Vatne
b06fb7e432 Release 2.0.0-alpha.0 2018-03-12 15:06:47 -07:00
Brent Vatne
a92ed83302 Fix tab icon height on horizontal / ipad 2018-03-12 15:06:47 -07:00
Brent Vatne
0c31bc44ea Make push, pop, and popToTop bubble like navigate (#3617) 2018-03-12 15:06:38 -07:00
Brent Vatne
8e5ee4d312 Use arrow function for isFocused 2018-03-12 09:56:39 -07:00
Brandon Smith
4bb8987ab7 Pass initialRouteKey into StackRouter (#3540) (#3702) 2018-03-09 11:32:01 -08:00
Brent Vatne
81a86fa091 Swap addListener out for isFocused prop on ResourceSavingSceneView (#3700) 2018-03-09 10:55:00 -08:00
Brent Vatne
47f357f332 Fix TabRouter-test 2018-03-09 10:46:05 -08:00
Brent Vatne
bdda6fa5be Add SwitchNavigator to 2.x 2018-03-07 17:35:15 -08:00
Ashoat Tevosyan
b097136f74 [Flow] Some updates, mostly from flow-typed (#3682)
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.
2018-03-07 11:29:25 -08:00
Ben Styles
c9b0219cec Allow passing null to onNavigationStateChange prop (#3683)
As seen here: react-navigation/react-navigation#360, we need to be able to pass null to turn off logging.
2018-03-07 14:19:00 -05:00
Eric Vicenti
ac83cf804c Fix issue in drawer actions (#3667)
* Fix issue in drawer actions

* Update DrawerView.js
2018-03-06 14:38:03 -08:00
Sirui Li
cf63521516 Flow type: SafeAreaView doesn't require children (#3670)
`children` prop should be optional.
2018-03-06 14:19:46 -08:00
corupta
7c488c8d49 Add activeLabelStyle and inactiveLabelStyle for DrawerItem (#3559)
* 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
2018-03-05 17:17:08 -08:00
Edward Drapkin
9005494e64 More specific injected Navigation props (#3645) 2018-03-05 16:33:42 -08:00
Brent Vatne
0daab8c55b Add isFocused helper to navigation and fix withNavigationFocus 2018-03-05 12:28:42 -08:00
Brent Vatne
ae98089337 Cache event subscribers and clean up after unmounting (#3648)
* 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
2018-03-05 11:27:57 -08:00
Yordis Prieto
57e37a8783 Fix typespec of back action creator (#3659) 2018-03-05 11:10:39 -08:00
Ashoat Tevosyan
b7994d28db Fix NavigationEventPayload.lastState type (#3664)
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)
2018-03-05 11:04:29 -08:00
Vishwesh Jainkuniya
f1bfdeee46 Fix: tabBar icons are not visible. (#3650)
* Fix: tabBar icons are not visible.

* Fix: tests.
2018-03-04 21:21:54 -08:00
Nicolas Beck
c6301abaed Add initialRouteKey for StackRouter (#3540)
* use initialRouteName as key when initializing StackRouter

* fix null headerLeft

* merge back

* fixed tests

* use config flag

* fixed snapshots

* implemented requested changes
2018-03-02 16:06:27 -08:00
Brent Vatne
4569ad49f9 Fix regression in error message for route config validation 2018-03-02 12:18:11 -08:00
Arseny Yankovsky
214eeb13fb Allow modification of SafeAreaView props (#3496)
* SafeAreaView fix

* Updated to only allow modification of forceInset property of SafeAreaView
2018-03-01 13:42:19 -08:00
Michał Pierzchała
416fe58cab Move contributing guide to CONTRIBUTING.md (#3631) 2018-03-01 10:11:30 -08:00
Eric Vicenti
2e47cbb3cb Drawer Router (#3618) 2018-02-27 18:34:05 -08:00
Brent Vatne
cd99dc8054 Update snapshots 2018-02-27 17:32:13 -08:00
Eric Vicenti
e27ad22c57 [BREAKING] New createNavigator API (#3392)
* New createNavigator and View API

See the RFC here:
https://github.com/react-navigation/rfcs/blob/master/text/0002-navigator-view-api.md

* shattered dreams of flow

* fix export

* Fix tab view issues found by brent
2018-02-27 17:27:58 -08:00
Brent Vatne
6785729fb5 Fix snapshots 2018-02-26 16:02:38 -08:00
Brent Vatne
d3b6e70d16 Clarify that people should not report Redux or MobX related integration issues here 2018-02-26 15:53:14 -08:00
Brent Vatne
5f32a48c16 Release 1.2.1 2018-02-26 14:04:44 -08:00
Brent Vatne
d5a0b5912b Apply StyleSheet.flatten properly to headerStyle. Fixes #3608 2018-02-26 14:04:36 -08:00
Yordis Prieto
13fd8acb20 fix typespec (#3583) 2018-02-26 12:25:13 -08:00
Serhii Palash
8fc8f3b8f7 Fix bug #3279 “Action within RESET doesn't trigger” (#3593)
https://github.com/react-navigation/react-navigation/issues/3279
2018-02-26 12:14:29 -08:00
Brent Vatne
a37473c5e4 Release 1.2.0 2018-02-25 17:46:44 -08:00
Brent Vatne
23eb0839cb Improve crossfade configuration for header 2018-02-25 17:44:16 -08:00
Brent Vatne
e84473db78 Use a closer-to-correct spring animation when releasing a gesture in CardStack (#3601) 2018-02-25 17:20:39 -08:00
Brent Vatne
c8531d0f38 Pop to top on TabNavigator when tapping already focused tab icon (#3589)
* 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
2018-02-25 16:33:20 -08:00
Vojtech Novak
276fb8f7b3 remove support for deprecated navigation actions (#3595)
* remove support for deprecated navigation actions

* remove deprecated action from flow definitions
2018-02-24 12:08:14 -08:00
Johan Ruokangas
ab758bcaaa Fix RFC link (#3594) 2018-02-24 12:50:31 +01:00
Matt Hamil
2bb91a6740 Updated README (#3567)
Changed wording in the Web Support section of README to reflect priority for previous 1.0 release.
2018-02-22 21:52:09 -08:00
Brent Vatne
ffa3a92534 First crack at publish from circle (#3574)
* 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
2018-02-22 16:39:41 -08:00
Brent Vatne
6dda8c30a9 Fix colors for card and header border on iOS 2018-02-22 12:58:33 -08:00
Brent Vatne
065fdf61d8 Several improvements to StackNavigation Header (#3568)
* Refactor to remove unused variables, styles, and outer Animated view

* Style cleanup

* Proof of concept blur background

* Clean it up and add flow interface

* Update snapshots
2018-02-21 18:29:43 -08:00
Brent Vatne
371a714b57 Release 1.1.2 2018-02-20 16:00:44 -08:00
Ron Arts
1d33b95c5f Bump react-native-safe-area-view dep to 0.7.0 for react-native-web support (#3553) 2018-02-20 15:44:20 -08:00
Mike Grabowski
593bc8a648 Improve Header performance a bit (#3556)
* 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
2018-02-20 15:44:10 -08:00
Brent Vatne
174a6e4175 Release 1.1.1 2018-02-19 18:18:38 -08:00
Brent Vatne
af991e5512 Release 1.1.0 2018-02-19 18:16:23 -08:00
Brent Vatne
0b0e9e9df5 Fix TabRouter to support shorthand route config 2018-02-19 18:16:23 -08:00
Brent Vatne
42b0ccca79 Release 1.1.0-rc.5 2018-02-19 18:16:23 -08:00
Brent Vatne
da6a960bb1 Fix regression in modular back button 2018-02-19 18:16:23 -08:00
Ron Arts
3ca47ec778 Fix react-native-web support for #3526 (#3546)
* MaskedViewIOS use broke react-native-web support, this fixes it.

* Fallback more gracefully.

* Actually return the value ...
2018-02-19 13:48:12 +01:00
Marcin Raburski
14ee56a20d getComponentForState made more generic (#2498) 2018-02-19 04:14:13 -08:00
Matthieu Lemoine
9d36daf48e Pass prevTransitionsProps to transitionConfig (#3304)
* Pass prevTransitionsProps to transitionConfig

* Remove flow type
2018-02-19 02:29:46 -08:00
Brent Vatne
055fdb2ffc Release 1.1.0-rc.4 2018-02-17 12:50:26 -08:00
Brent Vatne
b3bf80634d Move the back button handler subscription to the NavigationContainer constructor (#3542)
* 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
2018-02-17 12:50:04 -08:00
Brent Vatne
fafd0e8702 Cleanup around StackRouter (#3487)
* Make StackRouter a bit easier to read, update and add some comments, add an explicit test around stack and navigate

* Address feedback for clarity
2018-02-17 11:14:03 -08:00
Brent Vatne
d94045817c Release 1.1.0-rc.3 2018-02-17 09:42:45 -08:00
Brent Vatne
f0acaddf05 Fix headerLeft on first screen regression 2018-02-17 09:40:59 -08:00
Brent Vatne
9beb32ecac Update snapshots 2018-02-16 18:14:07 -08:00
Brent Vatne
29a29936bf Remove withNavigationFocus example until it's fixed 2018-02-16 18:10:33 -08:00
Brent Vatne
8961fef00b Bump version 2018-02-16 18:09:40 -08:00
Brent Vatne
021c7e54be Do not use hide views when swipe or animations are enabled. Improve withNavigationFocus example 2018-02-16 18:05:39 -08:00
Brent Vatne
27538cad94 Properly thread through childNavigation 2018-02-16 17:26:01 -08:00
Brent Vatne
9a8a50ef1d Release 1.1.0-rc.0 2018-02-16 17:07:28 -08:00
Brent Vatne
2c6dc35723 Revert "Revert "Add getParam navigation helper (#3510)" (#3532)"
This reverts commit 5febb81a1c.
2018-02-16 17:06:16 -08:00
Brent Vatne
3600ecbd9b Add back support for lazy tabs and use removeClippedSubviews (#3538)
* 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
2018-02-16 16:59:19 -08:00
Sébastien Lorber
c74f001b1c add withNavigationFocus HOC (#3512)
* add withNavigationFocus HOC

See:
- https://github.com/react-navigation/react-navigation/issues/51#issuecomment-276003658
- https://github.com/react-navigation/react-navigation/issues/51#issuecomment-278761705
- https://github.com/react-navigation/react-navigation/pull/3345#issuecomment-360260067

* typos

* remove unused import

* Add withNavigationFocus export

* add example TabsWithNavigationFocus

* add example TabsWithNavigationFocus

* withNavigationFocus: get navigation from context or props

* subs => subscriptions

* fix flow issues
2018-02-16 16:57:33 -08:00
Brent Vatne
7f4706e4cc Update snapshots 2018-02-16 12:45:57 -08:00
Brent Vatne
d0ef33b12f Several small changes related to header style commit 2018-02-16 12:42:44 -08:00
Brent Vatne
3c3668c952 Header transition presets with support for standard iOS transition style (#3526)
Header transition presets with approximate support for UIKit transition style
2018-02-16 12:41:59 -08:00
Brent Vatne
5febb81a1c Revert "Add getParam navigation helper (#3510)" (#3532)
This reverts commit 50dcb37cd7.
2018-02-15 13:24:40 -08:00
Peter Piekarczyk
50dcb37cd7 Add getParam navigation helper (#3510)
* 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
2018-02-15 10:14:08 -08:00
Ron Arts
69bca191a7 The Linking and BackHandler components are now both supported by react-native-web (#3494)
so there's no need to supply dummy replacements.
2018-02-13 12:23:26 -08:00
Sébastien Lorber
4df9198979 fix doc link (#3513) 2018-02-13 10:30:20 -08:00
Ashoat Tevosyan
0fc7f87173 Run Prettier on Flow libdef on precommit (#3495) 2018-02-12 14:45:50 -08:00
Brent Vatne
5b4d11ab5d Better orientation layout on playground 2018-02-12 11:53:23 -08:00
Brent Vatne
4d1cc285b9 Slightly improved margins on the iOS header back button 2018-02-09 21:19:02 -08:00
Brent Vatne
41725afa8a Use the correct iOS back icon 2018-02-09 20:08:56 -08:00
Brent Vatne
58b77d44ae Make Router({ RouteName: Component }) a valid way to configure a router (#3486)
* Make Router({routeName: Component}) a valid way to instantiate a route

* Update App.js in NavigationPlayground

* Fix route config flow type
2018-02-09 18:20:01 -08:00
Kazato Sugimoto
1d49b6e3fe Decode URI encoded string of deep link (#3455) 2018-02-09 16:26:20 -08:00
Brent Vatne
58b8a08af6 Update snapshots for TabView/TabNavigator 2018-02-09 14:22:31 -08:00
Maxime Florent Fankam
b11ea8a1d5 Allow swipeEnabled be a function (#3378)
* Allow swipeEnabled be a function with state param
2018-02-09 14:04:17 -08:00
Brent Vatne
3c2b977eca Number of lines in label for TabBarBottom is always 1 2018-02-09 13:51:04 -08:00
Brent Vatne
95565487ec Make it possible to go back to menu from key example and improve banner on menu screen (#3479)
* Make it possible to go back to menu from key example and improve banner on menu screen

* Fix NavigationPlayground flow error
2018-02-08 19:10:54 -08:00
Brent Vatne
a26d2acfca Bump to patch version 1.0.3 2018-02-08 18:24:20 -08:00
Brent Vatne
a1b3d2213d No need to have a conditional around slicing the routes array 2018-02-08 18:22:02 -08:00
Brent Vatne
eb39df507e Prevent navigation from getting in bad state when navigating back to route by key (#3478) 2018-02-08 18:20:14 -08:00
Brent Vatne
cca06bb530 Do not use contentInsetAdjustmentBehavior on iOS in ModalStack example 2018-02-08 16:14:45 -08:00
Eric Vicenti
2187d8fe66 Consistent treatment of route keys (#3474)
This problem was found and fixed by @matthargett and @jayphelps in #3397. I’m just rebasing and cleaning a few things up
2018-02-08 15:28:27 -08:00
Eric Vicenti
67f98b69eb Simpler implementation of withNavigation (#3476)
This will allow for refs with onRef (fixes #3461), and will avoid all these warnings from throwing during our tests
2018-02-08 14:20:52 -08:00
Brent Vatne
c0c5c86f63 Bump to patch version 1.0.2 2018-02-08 12:49:04 -08:00
Brent Vatne
4388b6403c Remove console logs from published version of navigation playground 2018-02-08 12:48:28 -08:00
Brent Vatne
2cb740fbf6 Only initialize the CardStack PanResponder if gestures are enabled 2018-02-08 12:36:26 -08:00
Brent Vatne
ac741a703b Remove extra scene in floating header if it hasn't been evicted due to transition yet 2018-02-08 12:32:09 -08:00
Brent Vatne
5641b42975 Revert "StackRouter block actions while transitioning (#3469)"
This reverts commit 858a0d7a53.
2018-02-08 11:49:25 -08:00
Brent Vatne
ea19ceaa6a Bump to minor version 1.0.1 2018-02-08 10:47:48 -08:00
Brent Vatne
57ae6e4736 Make TabRouter handle COMPLETE_TRANSITION in a child router without switching active index (#3473) 2018-02-08 10:46:12 -08:00
Eric Vicenti
858a0d7a53 StackRouter block actions while transitioning (#3469)
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
2018-02-08 09:02:47 -08:00
Dave Pack
cf36f22e68 Sync and switch SafeAreaView with standalone (#3452)
* add react-native-safe-area-view npm package

* remove local SafeAreaView, import from package in views

* update to latest react-native-safe-area-view

* update snapshots
2018-02-07 17:32:06 -08:00
Brent Vatne
7385c244b7 Add custom back button example 2018-02-07 10:42:06 -08:00
Brent Vatne
8bd25cf372 Bump to 1.0.0 2018-02-06 17:51:55 -08:00
Brent Vatne
20af8c688e Prevent push from bubbling up (#3454) 2018-02-06 17:49:52 -08:00
Brent Vatne
b0dccd7e88 Prevent pop and popToTop from bubbling up to parent stack (#3453) 2018-02-06 17:35:32 -08:00
Brent Vatne
c69a22f10e Bump version 2018-02-06 15:59:44 -08:00
Eric Vicenti
43a1c5ddbd Fix issue with StackRouter popToTop (#3451)
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.
2018-02-06 15:56:39 -08:00
Brent Vatne
e97d41cccf Bump version and update description 2018-02-06 14:53:08 -08:00
Brent Vatne
3e4ddc685a Remove Header.HEIGHT deprecation warning, no good alternative solution available yet 2018-02-06 14:48:44 -08:00
Brent Vatne
f62c728593 Bump version 2018-02-06 14:13:41 -08:00
Eric Vicenti
616f9a56f2 Fix StackRouter Replace Key Behavior (#3450)
Replace should actually provide new keys on the replaced route, use ‘newKey’ on the action if you want to define the new route key
2018-02-06 14:12:59 -08:00
Brent Vatne
3b93faa0fc Bump version 2018-02-06 13:01:46 -08:00
Eric Vicenti
333b2e4b68 StackNavigator Replace Action (#3440)
* Navigation replace action

The long awaited action to replace the a route in StackNavigator

* Fix flow maybe
2018-02-06 12:59:16 -08:00
Brent Vatne
7f50173cf1 Bump version 2018-02-06 12:49:43 -08:00
Brent Vatne
8432f67529 Add adaptive to TabBarBottom flow interface 2018-02-06 12:49:37 -08:00
Eric Vicenti
c72b44ce10 Fix focus event for initial screen (#3448) 2018-02-06 12:49:23 -08:00
Peter Steffey
149f5f5c66 Fix #2795 - Not reducing header height in landscape on iPad (#3251)
* Adding tablet check for small header

* Switching to Platform.isPad

* Moving fully to Platform.isPad, no isHeightConstrained
2018-02-06 10:40:03 -08:00
Peter Steffey
85f77fe903 Issue #2794 - Tab bar fix - Continued from #3041 (#3267)
* 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
2018-02-06 10:39:41 -08:00
Jay Phelps
d4b759606d remove $FlowFixMe comments left over, as flow is no longer used (#3439) 2018-02-06 14:59:38 +01:00
Brent Vatne
4d2609f4a8 Use a stack inside of drawer 2018-02-05 14:48:30 -08:00
Brent Vatne
0766ec963e Bump version 2018-02-05 11:43:53 -08:00
Brent Vatne
0759e8cc8f Fix tests 2018-02-05 11:43:33 -08:00
Eric Vicenti
fae1f71fb3 Key for completion action, to prevent eager didFocus (#3435)
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.
2018-02-05 11:33:00 -08:00
Eric Vicenti
03fbd98ce4 Fix Transitioner race condition (#3434)
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
2018-02-05 10:52:08 -08:00
Andrej Badin
63a6565afa Fix incorrect easing functions for CardStack (#3381)
* 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
2018-02-05 10:42:45 -08:00
dushaobindoudou
154aa85f70 remove unuseful SafeAreaView component (#3428) 2018-02-05 10:41:57 -08:00
Brent Vatne
a14002084f Bump version 2018-02-03 12:21:33 -08:00
Eric Vicenti
98cfd7a531 Fix events issue when swiping back (#3420) 2018-02-03 12:20:55 -08:00
Brent Vatne
282e5abac2 Better public example point under help 2018-02-03 11:05:53 -08:00
Brent Vatne
d6d1dd279d Clarify the "how can I help?" section 2018-02-03 11:04:36 -08:00
Brent Vatne
b0b7b556a3 Update the web section of README 2018-02-03 11:02:26 -08:00
Brent Vatne
56d233be8b Add a link to the website repository 2018-02-03 10:56:19 -08:00
Brent Vatne
cfda9b290b Update README again to improve wording of documentation section 2018-02-03 10:55:33 -08:00
Brent Vatne
bce5fde5cb Update README 2018-02-03 10:54:06 -08:00
Brent Vatne
33c6ac9ae7 Remove website, docs and related commit. (#3419)
- This now lives at https://github.com/react-navigation/react-navigation.github.io
2018-02-03 10:38:43 -08:00
Brent Vatne
189e7ee539 Bump version 2018-02-02 18:08:57 -08:00
Brent Vatne
dc06c50966 Update yarn.lock 2018-02-02 12:33:53 -08:00
Ashoat Tevosyan
b013cc98be Redux middleware for new event system (#3399)
* Add Redux bindings for new event system

* construct -> create

* react-navigation-redux-helpers
2018-02-02 11:58:35 -08:00
Ashoat Tevosyan
37c3a357fc Clean up old build process and Babel config (#3406) 2018-02-02 11:57:31 -08:00
Eric Vicenti
836a164693 New StackRouter Push Action (#3401) 2018-02-01 17:14:13 -08:00
Eric Vicenti
a9582c5dd3 StackRouter PopToTop Action (#3403) 2018-02-01 17:10:12 -08:00
Eric Vicenti
fe4079c495 StackRouter PopN Action (#3404) 2018-02-01 17:01:04 -08:00
Eric Vicenti
ed0306587c StackRouter Reset Action should match state key (#3400) 2018-02-01 11:25:30 -08:00
Eric Vicenti
c88ec60fe3 Fix and actually understand event emitter (#3367) 2018-02-01 09:42:48 -08:00
Ashoat Tevosyan
d0da40fa32 Add Flow libdef (#3391)
* 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
2018-02-01 09:34:35 -08:00
Eric Vicenti
7141f66efd Add key support to StackRouter navigate (#3393) 2018-01-31 19:48:04 -08:00
Ashoat Tevosyan
ffcf179883 metro-bundler -> metro (#3396) 2018-01-31 18:41:35 -08:00
Ashoat Tevosyan
441b9ffe10 Add NavigationPlayground Flow test to CI (#3385)
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`).
2018-01-30 15:57:06 -08:00
Ashoat Tevosyan
0d3d83bd90 Fix NavigationEvent types (#3384)
* 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
2018-01-30 15:49:47 -08:00
Ashoat Tevosyan
d1d81d7033 Update to RN 0.52 and Expo 25 (#3383)
* Update to RN 0.52 and Expo 25

* Rerecord snapshots for failing Jest tests

* jest-expo@25.1.0-beta.0

* jest-expo@25.1.0
2018-01-30 10:22:20 -08:00
Yao Hui Chua
a1fc566679 Support initialRouteParams for TabRouters (#3352) 2018-01-29 12:06:32 +01:00
Vojtech Novak
088e9e82ad rely on defaultProps in TouchableItem (#3374) 2018-01-28 23:33:21 +01:00
Eric Vicenti
dca37627a2 Add events support to redux example (#3368)
* Fixing redux

* Fix tab events and test event nested event subscriptions

* Add event support to redux example
2018-01-27 14:12:16 -08:00
Brent Vatne
50a3f8de93 Add headerBackImage, closes #1999 2018-01-27 13:53:44 -08:00
Patrick Monteith
e0de8b4dce Don't forward back actions to inactive children of TabRouters (#2121) 2018-01-27 13:21:47 -08:00
Freddy Harris
a62ad18b31 SafeAreaView style padding and inset collapse (#2917) 2018-01-27 12:59:51 -08:00
TheCodeTalker
77b5402404 navigation back fix in example (#3218) 2018-01-27 12:42:45 -08:00
Iacopo Pazzaglia
6c1ab47719 Allow tabBarTestIDProps to be a function that receive the focused status (#3303) 2018-01-27 12:37:36 -08:00
Brent Vatne
24bfab93b4 Manually unset transitionIsRunning rather than going through _onTransitionEnd after state change 2018-01-26 23:02:02 -08:00
Brent Vatne
f8426bef7e Clean up when transitioner state when bailing out early 2018-01-26 18:55:38 -08:00
Brent Vatne
afcce1a0c0 [Playground] Move sdkVersion back to 24 2018-01-26 17:34:08 -08:00
Brent Vatne
6f430b2f1e Revert updates to example package.json 2018-01-26 16:48:02 -08:00
Ashoat Tevosyan
427e89480f Bring back TypeDefinition.js and re-add Flow to NavigationPlayground (#3363)
* Bring back TypeDefinition.js and re-add Flow to NavigationPlayground

* Type EventListener correctly and ignore metro errors
2018-01-26 16:15:49 -08:00
Brent Vatne
4ae2a42a4d Remove NavigatorTypes (#3331) 2018-01-26 15:54:46 -08:00
Moriyoshi Koizumi
9e026ec2c8 Allow pure-wildcard route for nested navigators. (#2929)
* Allow pure-wildcard route for nested navigators.

* Treat empty paths as they are.
2018-01-26 15:52:59 -08:00
Dhruvdutt Jadhav
82572e73f3 Update Guide-Headers.md (#3335) 2018-01-26 15:45:39 -08:00
Dhruvdutt Jadhav
d84c320bd7 Update DrawerNavigator.md (#3337)
Improve code syntax
2018-01-26 15:45:06 -08:00
Dhruvdutt Jadhav
339732e956 Update TabNavigator.md (#3341)
Improve code syntax to match the rest of the code spinnets in docs
2018-01-26 15:44:18 -08:00
Nicolas Beck
8e0fdc67b8 Reset state instead of pushing new routes for navigation actions in Drawer (#3164) 2018-01-26 15:30:11 -08:00
Eric Vicenti
122f6cfcee Simple fix to back button behavior (#3362)
Should always provide the key to go back from
2018-01-26 11:02:27 -08:00
Eric Vicenti
0157a4c9e9 Navigation Event Subscriptions (#3345)
* 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
2018-01-25 00:13:28 -08:00
Brent Vatne
cbd1fee8a4 Remove website deploy from CI and clean up scripts (#3353)
* Remove website deploy from CI and clean up scripts

* Clobber unnecessary pieces from circle config
2018-01-24 20:48:58 -08:00
Brent Vatne
ebfbbe2c09 Delete some unnecessary noise 2018-01-24 20:21:16 -08:00
Brent Vatne
ecfa38bfd2 Remove flow (#3350)
* Remove flow types from src

* Finish removing Flow

* Clear out flow-typed, some flow mentions in docs, website flow usage, and some other config
2018-01-24 17:52:09 -08:00
Michael Duminy
276249c4c7 HeaderBackButton animation performance (#3305)
* header back button ripple animation performance

* replace InteractionManager with requestAnimationFrame

* getting used to flow typing
2018-01-23 14:03:51 -08:00
Grey Baker
1715513519 Update repository URL in package.json (#3342)
Update repository URL to reflect move from react-community to react-navigation organization.
2018-01-23 13:58:52 -08:00
Brent Vatne
2f4bacf6e2 Add RFC and website repos to issue template 2018-01-22 16:41:31 -08:00
Brent Vatne
05d342dac5 Update issue template 2018-01-22 16:22:03 -08:00
Pranav Kulkarni
a57f129cc0 Fix the section link for Reset action (#3316)
Sectional link to Reset section fails due to case difference.
2018-01-21 22:12:33 +05:30
Tien Pham
c0d76755e7 Update goBack docs (#2834)
* Update goBack docs

* Update Screen-Navigation-Prop.md
2018-01-21 02:07:24 +05:30
Adam Miskiewicz
b221afc80b Make examples use linked copy of react-navigation 2018-01-17 19:11:04 -08:00
Adam Miskiewicz
f895564605 Revert "Move examples to https://github.com/react-navigation/examples"
This reverts commit 36775007b0.
2018-01-17 14:43:28 -08:00
Brent Vatne
36775007b0 Move examples to https://github.com/react-navigation/examples 2018-01-17 12:43:24 -08:00
Brent Vatne
99c4d448b2 Bump version 2018-01-16 11:12:52 -08:00
Brent Vatne
8cf2953115 Revert adding SafeAreaView to TabBarTop 2018-01-16 11:12:06 -08:00
Brent Vatne
abbd88601f Bump version 2018-01-12 15:51:29 -08:00
Brent Vatne
ff6d6f4e5e Update icons in playground app and add some padding to banner 2018-01-12 15:50:12 -08:00
Brent Vatne
7fa0ef3aee Handle translucent status bar within Expo automatically.
- Escape hatch of `ReactNavigation.SafeAreaView.setStatusBarHeight()`.
- `if (Platform.OS === 'android') { ReactNavigation.SafeAreaView.setStatusBarHeight(0) }` to revert to old behavior.
2018-01-12 15:34:40 -08:00
Brent Vatne
6ac3bb90ed Bump version 2018-01-11 18:30:28 -08:00
Brent Vatne
627c487936 Revert "Issue #2794 - Fixing iPad iOS 11 Tab Bar Bottom Behavior (#3041)"
This reverts commit c7b73cd8b4.
2018-01-11 18:21:46 -08:00
Brent Vatne
f46bdff703 Bump version 2018-01-11 18:20:44 -08:00
Adam Miskiewicz
bc75a5b7b9 Use stiffness/damping/mass for card stack transition on React Native >= 50 (#3261) 2018-01-11 18:08:42 -08:00
混沌DM
50d5c8bc0a Set the default value of the DrawerNavigatorConfig correctly. (#3152)
* Set the default value of the DrawerNavigatorConfig correctly.

* update DrawerViewProps type
2018-01-09 14:58:27 +05:30
SteffeyDev
c7b73cd8b4 Issue #2794 - Fixing iPad iOS 11 Tab Bar Bottom Behavior (#3041)
* 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
2018-01-08 20:28:13 -06:00
rgovind92
e2e540c32d Fix drawer toggle (#3191)
* Fixed drawer toggle

* Fixed drawer toggle

* Update DrawerView.js
2018-01-06 10:40:56 -05:00
332 changed files with 23162 additions and 41090 deletions

View File

@@ -1,35 +1,3 @@
{
"env": {
// For RN example development
"development": {
"presets": ["react-native"],
"plugins": [
"transform-flow-strip-types"
]
},
// For Jest
"test": {
"presets": ["react-native"],
"plugins": [
"transform-flow-strip-types"
]
},
// For publishing to NPM for RN
"publish-rn": {
"presets": ["react-native-syntax"],
"plugins": [
"transform-flow-strip-types"
]
},
// For publishing to NPM for web
"publish-web": {
"presets": ["es2015", "stage-1", "react"],
"plugins": [
"transform-flow-strip-types",
["transform-define", {
"__DEV__": false
}]
]
}
}
"presets": ["react-native"]
}

View File

@@ -24,20 +24,17 @@ jobs:
tar -xz -C /tmp -f /tmp/docker-$VER.tgz
mv /tmp/docker/* /usr/bin
if [ "${CIRCLE_BRANCH}" == "master" ]; then
# deploy website
cd website && yarn && cd ../
yarn run build-docs
./scripts/deploy-website.sh
# deploy expo playground demo
# exp login -u "$EXPO_USERNAME" -p "$EXPO_PASSWORD"
# cd examples/NavigationPlayground && exp publish
fi
yarn global add exp
set +x
exp login -u "$EXPO_USERNAME" -p "$EXPO_PASSWORD"
set -x
cd examples/NavigationPlayground && yarn && exp publish --release-channel "${CIRCLE_SHA1}"
- save_cache:
key: v3-react-navigation-{{ .Branch }}-{{ checksum "package.json" }}
paths:
- ~/.cache/yarn
- ~/react-navigation/website/node_modules
- ~/react-navigation/examples/NavigationPlayground/node_modules
- ~/react-navigation/examples/ReduxExample/node_modules
notify:
webhooks:
- url: https://react-navigation-ci.now.sh

View File

@@ -1,5 +1,4 @@
coverage
flow-typed
flow
node_modules
lib*

View File

@@ -1,27 +1,24 @@
{
"extends": [
"plugin:flowtype/recommended",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"prettier",
"prettier/flowtype",
"prettier/react"
],
"parser": "babel-eslint",
"plugins": [
"react",
"flowtype",
"prettier"
],
"plugins": ["react", "prettier"],
"env": {
"jasmine": true
},
"rules": {
"prettier/prettier": ["error", {
"trailingComma": "es5",
"singleQuote": true
}],
"prettier/prettier": [
"error",
{
"trailingComma": "es5",
"singleQuote": true
}
],
"no-underscore-dangle": "off",
"no-use-before-define": "off",
@@ -30,44 +27,20 @@
"no-plusplus": "off",
"no-class-assign": "off",
"no-duplicate-imports": "off",
"import/extensions": "off",
"import/no-extraneous-dependencies": "off",
"import/no-unresolved": "off",
"react/jsx-filename-extension": [
"off", { "extensions": [".js", ".jsx"] }
],
"react/jsx-filename-extension": ["off", { "extensions": [".js", ".jsx"] }],
"react/sort-comp": "off",
"react/prefer-stateless-function": "off",
"react/no-deprecated": "off",
"react/forbid-prop-types": "warn",
"react/prop-types": "off",
"react/require-default-props": "off",
"react/no-unused-prop-types": "off",
"flowtype/boolean-style": [
"error",
"boolean"
],
"flowtype/no-weak-types": "off",
"flowtype/require-parameter-type": "off",
"flowtype/require-return-type": [
"off",
"always",
{
"annotateUndefined": "never"
}
],
"flowtype/require-valid-file-annotation": "error",
"flowtype/use-flow-type": "warn",
"flowtype/valid-syntax": "warn"
},
"settings": {
"flowtype": {
"onlyFilesWithFlowAnnotation": true
}
"react/no-unused-prop-types": "off"
},
"parserOptions": {
"ecmaVersion": 6,

View File

@@ -1,64 +0,0 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js
; Ignore "BUCK" generated dirs
.*/node_modules/react-native/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
; Ignore polyfills
.*/Libraries/polyfills/.*
; Ignore website node_modules react and react-native
<PROJECT_ROOT>/website/node_modules/react/.*
<PROJECT_ROOT>/website/node_modules/react-native/.*
<PROJECT_ROOT>/website/node_modules/fbjs/.*
; Ignore transpiled folders and examples folder
<PROJECT_ROOT>/lib
<PROJECT_ROOT>/lib-rn
<PROJECT_ROOT>/examples
<PROJECT_ROOT>/website/build
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
[options]
module.system=haste
emoji=true
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.json
module.file_ext=.native.js
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
unsafe.enable_getters_and_setters=true
[version]
^0.56.0

View File

@@ -1,21 +1,33 @@
## The issue tracker is reserved for bug reports only.
If you have a question or feature request, please try one of the following resources:
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
- _If describing a bug, tell us what happens. Please provide a repository with code and steps to reproduce the bug. **Not providing code that other people can run makes is significantly harder to fix your bug.** Provide a screenshot when possible_
- _If suggesting a change/improvement, explain the difference from current behavior_
- What code are you running and what is happening?
- Include a screenshot if it makes sense.
### Expected Behavior
- _If you're describing a bug, tell us what should happen_
- _If you're suggesting a change/improvement, tell us how it should work_
- 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.
### Your Environment

View File

@@ -1,17 +1,21 @@
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?
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
**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.
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.
The code must pass tests.
**Code formatting**
## Code formatting
Look around. Match the style of the rest of the codebase.
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.

4
.gitignore vendored
View File

@@ -8,8 +8,6 @@ jsconfig.json
# NodeJS
npm-debug.log
node_modules
lib-rn
lib
yarn-error.log
# OS X
@@ -19,4 +17,4 @@ yarn-error.log
.exponent
# Jest
coverage
coverage

161
CHANGELOG.md Normal file
View File

@@ -0,0 +1,161 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [2.11.2] - [2018-08-03](https://github.com/react-navigation/react-navigation/releases/tag/2.11.2)
### Changed
- Revert rename of pathUtils
## [2.11.1] - [2018-08-03](https://github.com/react-navigation/react-navigation/releases/tag/2.11.1)
### Changed
- Fix some exports related to the 2.11.0 changes to move stack navigator out of core
## [2.11.0] - [2018-08-03](https://github.com/react-navigation/react-navigation/releases/tag/2.11.0)
### Added
- Export some modules that are useful for moving stack navigator outside of core
## [2.10.0] - [2018-08-02](https://github.com/react-navigation/react-navigation/releases/tag/2.10.0)
### Added
- `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))
## [2.9.3] - [2018-07-26](https://github.com/react-navigation/react-navigation/releases/tag/2.9.3)
### Added
- Add `NavigationTestUtils` which can be imported by path to be used with jest snapshot testing.
## [2.9.2] - [2018-07-25](https://github.com/react-navigation/react-navigation/releases/tag/2.9.2)
### Added
- 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).
## [2.9.1] - [2018-07-24](https://github.com/react-navigation/react-navigation/releases/tag/2.9.1)
### Fixed
- 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)
### Fixed
- Typo in Header transition preset check.
## [2.9.0] - [2018-07-20](https://github.com/react-navigation/react-navigation/releases/tag/2.9.0)
### Added
- `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).
## [2.8.0] - [2018-07-19](https://github.com/react-navigation/react-navigation/releases/tag/2.8.0)
### Added
- `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).
## [2.7.0] - [2018-07-17](https://github.com/react-navigation/react-navigation/releases/tag/2.7.0)
### Added
- 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))
## [2.6.2] - [2018-07-06](https://github.com/react-navigation/react-navigation/releases/tag/2.6.2)
### Changed
- Relax vertical padding warnings on header.
## [2.6.1] - [2018-07-05](https://github.com/react-navigation/react-navigation/releases/tag/2.6.1)
### Added
- Warn for more invalid headerStyle properties (padding, top/right/bottom/left, position).
### Fixed
- Fixed missing header shadow on Android.
## [2.6.0] - [2018-07-04](https://github.com/react-navigation/react-navigation/releases/tag/2.6.0)
### Added
- [NavigationEvents](https://github.com/react-navigation/react-navigation/pull/4188) component as a declarative interface for subscribing to navigation focus events.
### Fixed
- Fix stack router child router delegation priority (https://github.com/react-navigation/react-navigation/commit/e8c1833053e37d28f0ce505ff323565abf23b6a2)
- 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.
## [2.5.5] - [2018-06-27](https://github.com/react-navigation/react-navigation/releases/tag/2.5.5)
### Added
- 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
## [2.5.4] - [2018-06-27](https://github.com/react-navigation/react-navigation/releases/tag/2.5.4)
### Fixed
- Header no longer sometimes flashes for 1 frame when using `header: null` on initial route of stack with floating header.
- Export `createSwitchNavigator` in react-navigation.web.js
## [2.5.3] - [2018-06-23](https://github.com/react-navigation/react-navigation/releases/tag/2.5.3)
### Fixed
- `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)
## [2.5.2] - [2018-06-23](https://github.com/react-navigation/react-navigation/releases/tag/2.5.2)
### Fixed
- Update react-navigation-drawer to fix regression in toggleDrawer
## [2.5.1] - [2018-06-22](https://github.com/react-navigation/react-navigation/releases/tag/2.5.1)
### Fixed
- `transitionConfig` in stack navigator no longer passes incorrect `fromTransitionProps` when navigating back
## [2.5.0] - [2018-06-22](https://github.com/react-navigation/react-navigation/releases/tag/2.5.0)
### Changed
- Refactor internals to make it play more nicely with web
### Fixed
- `const defaultGetStateForAction = SwitchBasedNavigator.router.getStateForAction` no longer throws error.
- Updated react-navigation-drawer to 0.4.1 which should fix issues related to automatically closing drawer when changing routes.
## [2.4.1] - [2018-06-21](https://github.com/react-navigation/react-navigation/releases/tag/2.4.1)
### Changed
- Improved examples
[Unreleased]: https://github.com/react-navigation/react-navigation/compare/2.11.2...HEAD
[2.11.2]: https://github.com/react-navigation/react-navigation/compare/2.11.1...2.11.2
[2.11.1]: https://github.com/react-navigation/react-navigation/compare/2.11.0...2.11.1
[2.11.0]: https://github.com/react-navigation/react-navigation/compare/2.10.0...2.11.0
[2.10.0]: https://github.com/react-navigation/react-navigation/compare/2.9.3...2.10.0
[2.9.3]: https://github.com/react-navigation/react-navigation/compare/2.9.2...2.9.3
[2.9.2]: https://github.com/react-navigation/react-navigation/compare/2.9.1...2.9.2
[2.9.1]: https://github.com/react-navigation/react-navigation/compare/2.9.0...2.9.1
[2.9.0]: https://github.com/react-navigation/react-navigation/compare/2.8.0...2.9.0
[2.8.0]: https://github.com/react-navigation/react-navigation/compare/2.7.0...2.8.0
[2.7.0]: https://github.com/react-navigation/react-navigation/compare/2.6.2...2.7.0
[2.6.2]: https://github.com/react-navigation/react-navigation/compare/2.6.1...2.6.2
[2.6.1]: https://github.com/react-navigation/react-navigation/compare/2.6.0...2.6.1
[2.6.0]: https://github.com/react-navigation/react-navigation/compare/2.5.5...2.6.0
[2.5.5]: https://github.com/react-navigation/react-navigation/compare/2.5.4...2.5.5
[2.5.4]: https://github.com/react-navigation/react-navigation/compare/2.5.3...2.5.4
[2.5.3]: https://github.com/react-navigation/react-navigation/compare/2.5.2...2.5.3
[2.5.2]: https://github.com/react-navigation/react-navigation/compare/2.5.1...2.5.2
[2.5.1]: https://github.com/react-navigation/react-navigation/compare/2.5.0...2.5.1
[2.5.0]: https://github.com/react-navigation/react-navigation/compare/2.4.1...2.5.0
[2.4.1]: https://github.com/react-navigation/react-navigation/compare/2.4.0...2.4.1

43
COMMUNITY_RESOURCES.md Normal file
View File

@@ -0,0 +1,43 @@
## Community resources
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)
* [Whats Happening with Navigation in React Native?](https://blog.revisify.com/whats-happening-with-navigation-in-react-native-c193535888c3)
#### Example Projects
* [Yaba-Social](https://github.com/allpwrfulroot/yaba-social)
* [React Native Boilerplate with React Navigation and Redux integration](https://github.com/verybluebot/react-native-boilerplate)
#### Libraries
* [react-navigation-addons](https://github.com/satya164/react-navigation-addons)
* [react-navigation-props-mapper](https://github.com/vonovak/react-navigation-props-mapper)

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
# Contributing to React Navigation
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!

7
NavigationTestUtils.js Normal file
View File

@@ -0,0 +1,7 @@
import { _TESTING_ONLY_reset_container_count } from './src/createNavigationContainer';
export default {
resetInternalState: () => {
_TESTING_ONLY_reset_container_count();
},
};

143
README.md
View File

@@ -1,152 +1,53 @@
# React Navigation
[![npm version](https://badge.fury.io/js/react-navigation.svg)](https://badge.fury.io/js/react-navigation) [![codecov](https://codecov.io/gh/react-community/react-navigation/branch/master/graph/badge.svg)](https://codecov.io/gh/react-community/react-navigation) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactnavigation.org/docs/guides/contributors)
*Learn once, navigate anywhere.*
[![npm version](https://badge.fury.io/js/react-navigation.svg)](https://badge.fury.io/js/react-navigation) [![codecov](https://codecov.io/gh/react-navigation/react-navigation/branch/master/graph/badge.svg)](https://codecov.io/gh/react-navigation/react-navigation) [![CircleCI badge](https://circleci.com/gh/react-navigation/react-navigation/tree/master.svg?style=shield)](https://circleci.com/gh/react-navigation/react-navigation/tree/master) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactnavigation.org/docs/contributing.html)
React Navigation is born from the React Native community's need for an extensible yet easy-to-use navigation solution based on Javascript.
React Navigation is the result of a collaboration between developers from Facebook, Expo and the React community at large: it replaces and improves upon several navigation libraries in the ecosystem, including Ex-Navigation, React Native's Navigator and NavigationExperimental components.
* [Installation](#installation)
* [Community contributions](#community-contributions)
* [Introduction to the library](#introduction-to-the-library)
* [Basic Tutorials](#basic-tutorials)
* [Intermediate Concepts](#intermediate-concepts)
* [Advanced Topics](#advanced-topics)
* [Comparisons and Discussion](#comparisons-and-discussion)
* [Example Projects](#example-projects)
* [Libraries](#libraries)
* [FAQs](#faqs)
* [When is version 1.0.0 going to be released?](#when-is-version-100-going-to-be-released)
* [I'm having troubles using the library, what can I do?](#im-having-troubles-using-the-library-what-can-i-do)
* [My app is really slow!](#my-app-is-really-slow)
* [How can I help?](#how-can-i-help)
* [Is this the only library available for navigation?](#is-this-the-only-library-available-for-navigation)
* [Can I use this library for web?](#can-i-use-this-library-for-web)
* [Code of conduct](#code-of-conduct)
* [License](#license)
## Installation
Since the library is a JS-based solution, to install the latest version of react-navigation you only need to run:
```bash
yarn add react-navigation
```
```bash
yarn add react-navigation
```
or
or
```bash
npm install --save react-navigation
```
```bash
npm install --save react-navigation
```
## Get Started
## Documentation
To learn how the library work, head to the [introduction](https://reactnavigation.org/docs/intro/) on the website for a quick tutorial that will cover all the basics - or try it out [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
* 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).
#### Advanced guides
## Try it out
* [Redux integration](https://reactnavigation.org/docs/guides/redux)
* [Deep linking](https://reactnavigation.org/docs/guides/linking)
#### React Navigation API
* [Navigators](https://reactnavigation.org/docs/navigators/)
* [Routers](https://reactnavigation.org/docs/routers/)
* [Views](https://reactnavigation.org/docs/views/)
## Community contributions
A lot of developers poured their knowledge in blog posts, and other repos - we will try to keep here a list of tutorials and 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)
* [Whats Happening with Navigation in React Native?](https://blog.revisify.com/whats-happening-with-navigation-in-react-native-c193535888c3)
#### Example Projects
* [Yaba-Social](https://github.com/allpwrfulroot/yaba-social)
* [React Native Boilerplate with React Navigation and Redux integration](https://github.com/verybluebot/react-native-boilerplate)
#### Libraries
* [react-navigation-addons](https://github.com/satya164/react-navigation-addons)
* [react-navigation-props-mapper](https://github.com/vonovak/react-navigation-props-mapper)
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
#### When is version 1.0.0 going to be released?
As soon as all the tasks [here](https://github.com/react-community/react-navigation/issues/2585) have been completed. You can read more about it in the [blog](https://reactnavigation.org/blog/2017/9/Renewed-v1).
(in the meantime, you can find the changelog for every release [here](https://github.com/react-community/react-navigation/releases))
#### I'm having troubles using the library, what can I do?
Head to the [issues](https://github.com/react-community/react-navigation/issues) and do a quick search: if you think you are experiencing a bug chances are somebody already opened an issue for it. If instead you are having more general problems, use [Stack Overflow](https://stackoverflow.com/search?q=react-navigation) - which is better suited and helps keeping the Issues section of the repo clean. Alternatively you could join the [Reactiflux](https://www.reactiflux.com/) community on Discord where there are React Native and React Navigation channels with helpful people who might be able to answer you.
You should **only** open a new issue if you believe that you are experiencing a bug or have a feature request, and please **follow** the dedicated template - it will help everyone helping you (and may get closed if it doesn't).
#### My app is really slow!
We are aware that the performances can be improved - we will work on this (keep an eye on the roadmap linked above). In the meantime, please refer to these few issues for specific information regarding:
* [Tab Navigators](https://github.com/react-community/react-navigation/issues/739)
* [Stack Navigators](https://github.com/react-community/react-navigation/issues/608)
In particular, refer to [this comment](https://github.com/react-community/react-navigation/issues/608#issuecomment-328635042) (and the [one after](https://github.com/react-community/react-navigation/issues/608#issuecomment-333386346) that) to learn more about how you can try improving the performance of your code.
See [the help page](https://reactnavigation.org/en/help.html).
#### How can I help?
Glad you ask! 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:
1. 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.
1. Creating public example repos of navigation problems you have solved.
1. Answering questions on [Stack Overflow](https://stackoverflow.com/search?q=react-navigation). Alternatively, asking questions on Stack Overflow instead of opening an issue.
1. Answering questions in our [Reactiflux](https://www.reactiflux.com/) channel.
1. Providing feedback on the open [PRs](https://github.com/react-community/react-navigation/pulls).
If you feel brave enough you can submit a PR: follow the [Contributors guide](https://reactnavigation.org/docs/guides/contributors) 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!
See our [Contributing Guide](CONTRIBUTING.md)!
#### Is this the only library available for navigation?
No: there are some other libraries - which, depending on your project, can be better or worse suited for your project. They differ in the approach and implementation from `react-navigation`, but share the common goal of helping you create a good React Native application; you can find a general round up in the [React Native docs](http://facebook.github.io/react-native/docs/navigation.html).
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?
This library originally planned to support web too - but at the moment [it is not a priority](https://github.com/react-community/react-navigation/issues/2585#issuecomment-330338793) for v1.0; a lot of work is necessary to reach it as-is and we had to freeze this support (consider it ["experimental"](https://reactnavigation.org/docs/guides/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
@@ -154,4 +55,4 @@ This library has adopted a Code of Conduct that we expect project participants t
## License
React-navigation is licensed under the [BSD 2-clause "Simplified" License](https://github.com/react-community/react-navigation/blob/master/LICENSE).
React Navigation is licensed under the [BSD 2-clause "Simplified" License](https://github.com/react-community/react-navigation/blob/master/LICENSE).

12
assetsTransformer.js Normal file
View File

@@ -0,0 +1,12 @@
/**
* This file is needed to hijack asset imports so that test files don't attempt
* to import them as JavaScript modules.
* See https://github.com/facebook/jest/issues/2663#issuecomment-317109798
*/
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};

View File

@@ -1,183 +0,0 @@
# React Navigation Contributor Guide
Want to help improve React Navigation? Your help would be greatly appreciated!
Here are some of some of the ways to contribute to the project:
- [Reporting Bugs](#Reporting-Bugs)
- [Improving the Documentation](#Improving-the-Documentation)
- [Responding to Issues](#Responding-to-Issues)
- [Bug Fixes](#Bug-Fixes)
- [Suggesting a Feature](#Suggesting-a-Feature)
- [Big Pull Requests](#Big-Pull-Requests)
And here are a few helpful resources to aid in getting started:
- [Issue Template](#Issue-Template)
- [Pull Request Template](#Pull-Request-Template)
- [Forking the Repository](#Forking-the-Repository)
- [Code Review Guidelines](#Code-Review-Guidelines)
- [Run the Example App](#Run-the-Example-App)
- [Run the Website](#Run-the-Website)
- [Run Tests and Type-Checking](#Run-Tests-and-Type-Checking)
> Note that we used Yarn in the examples below but you're welcome to use NPM instead.
## Contributing
### Reporting Bugs
You can't write code without writing the occasional bug. Especially as React Navigation is in beta and moving quickly, bugs happen. When you think you've found one here's what to do:
1. Search the existing issues for one like what you're seeing. If you see one, add a 👍 reaction (please no +1 comments). Read through the comments and see if you can provide any more valuable information to the thread
2. If there are no other issues like yours then create a new one. Be sure to follow the [issue template](https://github.com/react-community/react-navigation/blob/master/.github/ISSUE_TEMPLATE.md).
Creating a high quality reproduction is critical. Without it we likely can't fix the bug and, in an ideal situation, you'll find out that it's not actually a bug of the library but simply done incorrectly in your project. Instant bug fix!
### Improving the Documentation
Any successful projects needs quality documentation and React Navigation is no different.
The docs are currently organized as follows
- __Getting Started__: Introduction and basics of React Navigation. Help people get up and running with the package quickly. Introduce and demonstrate core functionality.
- __Navigators__: API documentation for the included navigators and supporting APIs
- __Advanced Guides__: (Advanced) Beyond the basics, what can you do with React Navigation? Discuss and demonstrate that here.
- __Routers__: (Advanced) API documentation for the included routers and how to use/customize them
- __Views__: (Advanced) API documentation for the included views and how to use/customize them
The documentation isn't fixed to what categories and documents currently exist. If your documentation contributation is appropriate for any existing document, add it there. If it makes sense to create a new document for your contribution please do so and add it to the docs index.
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 instructions for running the website.
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 `yarn run build-docs` from the `react-navigation` root folder.
### Responding to Issues
Another great way to contribute to React Navigation is by responding to issues. Maybe it's answering someone's question, pointing out a small typo in their code, or helping them put together a reproduction. If you're interested in a more active role in React Navigation start with responding to issues - not only is it helpful but it demonstrates your commitment and knowledge of the code!
### Bug Fixes
Find a bug, fix it up, all day long you'll have good luck! Like it was mentioned earlier, bugs happen. If you find a bug do the following:
1. Check if a pull request already exists addressing that bug. If it does give it a review and leave your comments
2. If there isn't already a pull request then figure out the fix! If it's relatively small go ahead and fix it and submit a pull request. If it's a decent number of changes file an issue first so we can discuss it (see the [Big Pull Requests](#big-pull-requests) section)
3. If there is an issue related to that bug leave a comment on it, linking to your pull request, so others know it's been addressed.
Check out the [help wanted](https://github.com/react-community/react-navigation/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) and [good first issue](https://github.com/react-community/react-navigation/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) tags to see where you can start helping out!
### Suggesting a Feature
Is there something you want to see from React Navigation? Go ahead and open and issue, describe what it is you want to accomplish and why you want to accomplish that. A few things to consider/add
1. Is there already a way to do this and you want to simplify it?
2. Do you have any thoughts on how to implement this feature? Have you done something similar already?
Hold off on submitting feature pull requests until the feature has been discussed. Once the feature has been established and agreed upon, create the pull request (following the [big pull requests](#big-pull-requests) guide).
### Big Pull Requests
For any changes that will add/remove/modify multiple files in the project (new features or bug fixes) hold off on writing code right away. There's a few reasons for that
1. Big pull requests take a lot of time to review and it's sometimes hard to pick up the context
2. Often you may not have to make as big of a change as you expect
With that in mind, here's the suggestion
1. Open an issue and clearly define what it is you want to accomplish and how you intend to accomplish it
2. Discuss that solution with the community and maintainers. Provide context, establish edge cases, and figure out the design
3. Decide on a plan of action
4. Write the code and submit the PR
5. Review the PR. This can take some time but, if you followed the steps above, hopefully it won't take too much time.
The reason we want to do this is to save everyone time. Maybe that feature already exists but isn't documented? Or maybe it doesn't fit with the library. Regardless, by discussing a major change up front you're saving your time and others time as well.
## Information
### Issue Template
Before submitting and issue please take a look at the [issue template](https://github.com/react-community/react-navigation/blob/master/.github/ISSUE_TEMPLATE.md) and follow it. This is in place to help everyone better understand the issue you're having and reduce the back and forth to get the necessary information.
Yes, it takes time and effort to complete the issue template. But that's the only way to ask high quality questions that actually get responses.
Would you rather take 1 minute to create an incomplete issue report and wait months to get any sort of response? Or would you rather take 20 minutes to fill out a high quality issue report, with all the necessary elements, and get a response in days? It's also a respectful thing to do for anyone willing to take the time to review your issue.
### Pull Request Template
Much like the issue template, the [pull request template](https://github.com/react-community/react-navigation/blob/master/.github/PULL_REQUEST_TEMPLATE.md) lays out instructions to ensure your pull request gets reviewd in a timely manner and reduces the back and forth. Make sure to look it over before you start writing any code.
### Forking the Repository
- Fork [`react-navigation`](https://github.com/react-community/react-navigation) on GitHub
- Run these commands in the terminal to download locally and install it:
```bash
git clone https://github.com/<USERNAME>/react-navigation.git
cd react-navigation
git remote add upstream https://github.com/react-community/react-navigation.git
yarn install
```
### Code Review Guidelines
Look around. Match the style of the reset of the codebase. This project uses ESLint and Flow to ensure consistency throughout the project. You can check your project by running
```bash
yarn run eslint
yarn run flow-check
```
If any errors occur you'll either have to manually fix them or you can attempt to automatically fix them by running `yarn run format`.
### Run the Example App
```bash
yarn install
cd examples/NavigationPlayground
yarn install
yarn start
```
You will be show a QR code to scan in the Expo app. You can get Expo [here](https://docs.expo.io/versions/latest/index.html) if you don't have it yet.
All examples:
- [NavigationPlayground](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground)
- [ReduxExample](https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample)
- [SafeAreaExample](https://github.com/react-community/react-navigation/tree/master/examples/SafeAreaExample)
Commands are the same as above for any of the example apps. If you run into any issues, please try the following to start fresh:
```bash
watchman watch-del-all
yarn start -- --reset-cache
```
### Run the Website
For development mode and live-reloading:
```bash
cd website
yarn install
yarn start
```
To run the website in production mode with server rendering:
```bash
yarn run prod
```
If you've made any changes to the `docs` directory you'll need to run `yarn run build-docs` from the root of the project before they're picked up by the website.
### Run Tests and Type-Checking
React Navigation has tests implemented in [Jest](https://facebook.github.io/jest/) and type-checking is managed by [Flow](https://flow.org/). To run either of these, from the React Navigation directory, run either of the following commands (after installing the `node_modules`) to run tests or type-checking.
```bash
yarn run jest
yarn run flow-check
```
These commands will be run by our CI and are required to pass before any contributtions are merged.

View File

@@ -1,191 +0,0 @@
# DrawerNavigator
Used to easily set up a screen with a drawer navigation. For a live example please see [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
```js
class MyHomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Notifications',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
const MyApp = DrawerNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
});
```
To open and close drawer, navigate to `'DrawerOpen'` and `'DrawerClose'` respectively.
```js
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
```
If you would like to toggle the drawer you can navigate to `'DrawerToggle'`, and this will choose which navigation is appropriate for you given the drawers current state.
```js
// fires 'DrawerOpen'/'DrawerClose' accordingly
this.props.navigation.navigate('DrawerToggle');
```
## API Definition
```js
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
```
### RouteConfigs
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](/docs/api/navigators/StackNavigator.md#routeconfigs) from `StackNavigator`.
### DrawerNavigatorConfig
- `drawerWidth` - Width of the drawer or a function returning it.
- `drawerPosition` - Options are `left` or `right`. Default is `left` position.
- `contentComponent` - Component used to render the content of the drawer, for example, navigation items. Receives the `navigation` prop for the drawer. Defaults to `DrawerItems`. For more information, see below.
- `contentOptions` - Configure the drawer content, see below.
- `useNativeAnimations` - Enable native animations. Default is `true`.
- `drawerBackgroundColor` - Use the Drawer background for some color. The Default is `white`.
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.
### Providing a custom `contentComponent`
The default component for the drawer is scrollable and only contains links for the routes in the RouteConfig. You can easily override the default component to add a header, footer, or other content to the drawer. By default the drawer is scrollable and supports iPhone X safe area. If you customize the content, be sure to wrap the content in a SafeAreaView:
```js
import { DrawerItems, SafeAreaView } from 'react-navigation';
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
```
### `contentOptions` for `DrawerItems`
- `items` - the array of routes, can be modified or overridden
- `activeItemKey` - key identifying the active route
- `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
- `onItemPress(route)` - function to be invoked when an item is pressed
- `itemsContainerStyle` - style object for the content section
- `itemStyle` - style object for the single item, which can contain an Icon and/or a Label
- `labelStyle` - style object to overwrite `Text` style inside content section, when your label is a string
- `iconContainerStyle` - style object to overwrite `View` icon container styles.
#### Example:
```js
contentOptions: {
activeTintColor: '#e91e63',
itemsContainerStyle: {
marginVertical: 0,
},
iconContainerStyle: {
opacity: 1
}
}
```
### Screen Navigation Options
#### `title`
Generic title that can be used as a fallback for `headerTitle` and `drawerLabel`
#### `drawerLabel`
String, React Element or a function that given `{ focused: boolean, tintColor: string }` returns a React.Node, to display in drawer sidebar. When undefined, scene `title` is used
#### `drawerIcon`
React Element or a function, that given `{ focused: boolean, tintColor: string }` returns a React.Node, to display in drawer sidebar
#### `drawerLockMode`
Specifies the [lock mode](https://facebook.github.io/react-native/docs/drawerlayoutandroid.html#drawerlockmode) of the drawer. This can also update dynamically by using screenProps.drawerLockMode on your top level router.
### 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 and nav options as props.screenProps */}
/>
```
### Nesting `DrawerNavigation`
Please bear in mind that if you nest the DrawerNavigation, the drawer will show below the parent navigation.

View File

@@ -1,63 +0,0 @@
# Navigators
Navigators allow you to define your 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:
```js
import { NavigationActions } from 'react-navigation';
const AppNavigator = StackNavigator(SomeAppRouteConfigs);
class App extends React.Component {
someEvent() {
// call navigate for AppNavigator here:
this.navigator && this.navigator.dispatch(
NavigationActions.navigate({ routeName: someRouteName })
);
}
render() {
return (
<AppNavigator ref={nav => { this.navigator = nav; }} />
);
}
}
```
Please notice that this solution should only be used on the top level navigator.
## 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.
Top-level navigators accept the following props:
### `onNavigationStateChange(prevState, newState, action)`
Function that gets called every time navigation state managed by the navigator changes. It receives the previous state, the new state of the navigation and the action that issued state change. By default it prints state changes to the console.
### `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.

View File

@@ -1,230 +0,0 @@
# StackNavigator
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.
```jsx
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
}
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Profile', {name: 'Lucy'})}
title="Go to Lucy's profile"
/>
);
}
}
const ModalStack = StackNavigator({
Home: {
screen: MyHomeScreen,
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
});
```
## API Definition
```js
StackNavigator(RouteConfigs, StackNavigatorConfig)
```
### RouteConfigs
The route configs object is a mapping from route name to a route config, which tells the navigator what to present for that route.
```js
StackNavigator({
// For each screen that you can navigate to, create a new entry like this:
Profile: {
// `ProfileScreen` is a React component that will be the main content of the screen.
screen: ProfileScreen,
// When `ProfileScreen` is loaded by the StackNavigator, it will be given a `navigation` prop.
// Optional: When deep linking or using react-navigation in a web app, this path is used:
path: 'people/:name',
// The action and route params are extracted from the path.
// Optional: Override the `navigationOptions` for the screen
navigationOptions: ({navigation}) => ({
title: `${navigation.state.params.name}'s Profile'`,
}),
},
...MyOtherRoutes,
});
```
### StackNavigatorConfig
Options for the router:
- `initialRouteName` - Sets the default screen of the stack. Must match one of the keys in route configs.
- `initialRouteParams` - The params for the initial route
- `navigationOptions` - Default navigation options to use for screens
- `paths` - A mapping of overrides for the paths set in the route configs
Visual options:
- `mode` - Defines the style for rendering and transitions:
- `card` - Use the standard iOS and Android screen transitions. This is the default.
- `modal` - Make the screens slide in from the bottom which is a common iOS pattern. Only works on iOS, has no effect on Android.
- `headerMode` - Specifies how the header should be rendered:
- `float` - Render a single header that stays at the top and animates as screens are changed. This is a common pattern on iOS.
- `screen` - Each screen has a header attached to it and the header fades in and out together with the screen. This is a common pattern on Android.
- `none` - No header will be rendered.
- `cardStyle` - Use this prop to override or extend the default style for an individual card in stack.
- `transitionConfig` - Function to return an object that is merged with the default screen transitions (take a look at TransitionConfig in [type definitions](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js)). Provided function will be passed the following arguments:
- `transitionProps` - Transition props for the new screen.
- `prevTransitionProps` - Transitions props for the old screen.
- `isModal` - Boolean specifying if screen is modal.
- `onTransitionStart` - Function to be invoked when the card transition animation is about to start.
- `onTransitionEnd` - Function to be invoked once the card transition animation completes.
### Screen Navigation Options
#### `title`
String that can be used as a fallback for `headerTitle`. Additionally, will be used as a fallback for `tabBarLabel` (if nested in a TabNavigator) or `drawerLabel` (if nested in a DrawerNavigator).
#### `header`
React Element or a function that given `HeaderProps` returns a React Element, to display as a header. Setting to `null` hides header.
#### `headerTitle`
String, React Element or React Component used by the header. Defaults to scene `title`. When a component is used, it receives `allowFontScaling`, `style` and `children` props. The title string is passed in `children`.
#### `headerTitleAllowFontScaling`
Whether header title font should scale to respect Text Size accessibility settings. Defaults to true.
#### `headerBackTitle`
Title string used by the back button on iOS, or `null` to disable label. Defaults to the previous scene's `headerTitle`.
#### `headerTruncatedBackTitle`
Title string used by the back button when `headerBackTitle` doesn't fit on the screen. `"Back"` by default.
#### `headerRight`
React Element to display on the right side of the header.
#### `headerLeft`
React Element or Component to display on the left side of the header. When a component is used, it receives a number of props when rendered (`onPress`, `title`, `titleStyle` and more - check `Header.js` for the complete list).
#### `headerStyle`
Style object for the header
#### `headerTitleStyle`
Style object for the title component
#### `headerBackTitleStyle`
Style object for the back title
#### `headerTintColor`
Tint color for the header
#### `headerPressColorAndroid`
Color for material ripple (Android >= 5.0 only)
#### `gesturesEnabled`
Whether you can use gestures to dismiss this screen. Defaults to true on iOS, false on Android.
#### `gestureResponseDistance`
Object to override the distance of touch start from the edge of the screen to recognize gestures. It takes the following properties:
- `horizontal` - *number* - Distance for horizontal direction. Defaults to 25.
- `vertical` - *number* - Distance for vertical direction. Defaults to 135.
#### `gestureDirection`
String to override the direction for dismiss gesture. `default` for normal behaviour or `inverted` for right-to-left swipes.
### 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.
You can view these examples directly on your phone by visiting [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
#### Modal StackNavigator with Custom Screen Transitions
```js
const ModalNavigator = StackNavigator(
{
Main: { screen: Main },
Login: { screen: Login },
},
{
headerMode: 'none',
mode: 'modal',
navigationOptions: {
gesturesEnabled: false,
},
transitionConfig: () => ({
transitionSpec: {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
},
screenInterpolator: sceneProps => {
const { layout, position, scene } = sceneProps;
const { index } = scene;
const height = layout.initHeight;
const translateY = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [height, 0, 0],
});
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return { opacity, transform: [{ translateY }] };
},
}),
}
);
```
Header transitions can also be configured using `headerLeftInterpolator`, `headerTitleInterpolator` and `headerRightInterpolator` fields under `transitionConfig`.

View File

@@ -1,207 +0,0 @@
# TabNavigator
Used to easily set up a screen with several tabs with a TabRouter. For a live example please see [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
```js
class MyHomeScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Home',
// Note: By default the icon is only shown on iOS. Search the showIcon option below.
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
});
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
}, {
tabBarPosition: 'top',
animationEnabled: true,
tabBarOptions: {
activeTintColor: '#e91e63',
},
});
```
## API Definition
```js
TabNavigator(RouteConfigs, TabNavigatorConfig)
```
### RouteConfigs
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](/docs/api/navigators/StackNavigator.md#routeconfigs) from `StackNavigator`.
### TabNavigatorConfig
- `tabBarComponent` - Component to use as the tab bar, e.g. `TabBarBottom`
(this is the default on iOS), `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.
- `configureTransition` - a function that, given `currentTransitionProps` and `nextTransitionProps`, returns a configuration object that describes the animation between tabs.
- `initialLayout` - Optional object containing the initial `height` and `width`, can be passed to prevent the one frame delay in [react-native-tab-view](https://github.com/react-native-community/react-native-tab-view#avoid-one-frame-delay) rendering.
- `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.
- `tabStyle` - Style object for the tab.
- `allowFontScaling` - Whether label font should scale to respect Text Size accessibility settings, default is true.
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.0 only).
- `scrollEnabled` - Whether to enable scrollable tabs.
- `tabStyle` - Style object for the tab.
- `indicatorStyle` - Style object for the tab indicator (line at the bottom of the tab).
- `labelStyle` - Style object for the tab label.
- `iconStyle` - Style object for the tab icon.
- `style` - Style object for the tab bar.
- `allowFontScaling` - Whether label font should scale to respect Text Size accessibility settings, default is true.
Example:
```js
tabBarOptions: {
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 100,
},
style: {
backgroundColor: 'blue',
},
}
```
### Screen Navigation Options
#### `title`
Generic title that can be used as a fallback for `headerTitle` and `tabBarLabel`.
#### `tabBarVisible`
True or false to show or hide the tab bar, if not set then defaults to true.
#### `swipeEnabled`
True or false to enable or disable swiping between tabs, if not set then defaults to TabNavigatorConfig option swipeEnabled.
#### `tabBarIcon`
React Element or a function that given `{ focused: boolean, tintColor: string }` returns a React.Node, to display in tab bar.
#### `tabBarLabel`
Title string of a tab displayed in the tab bar or React Element or a function that given `{ focused: boolean, tintColor: string }` returns a React.Node, to display in tab bar. When undefined, scene `title` is used. To hide, see `tabBarOptions.showLabel` in the previous section.
#### `tabBarOnPress`
Callback to handle tap events; the argument is an object containing:
* the `previousScene: { route, index }` which is the scene we are leaving
* the `scene: { route, index }` that was tapped
* the `jumpToIndex` method that can perform the navigation for you
Useful for adding a custom logic before the transition to the next scene (the tapped one) starts.
### Navigator Props
The navigator component created by `TabNavigator(...)` takes the following props:
- `screenProps` - Pass down extra options to child screens and navigation options, for example:
```jsx
const TabNav = TabNavigator({
// config
});
<TabNav
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>
```

View File

@@ -1,131 +0,0 @@
# Routers
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/tab)
## 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 [built-in navigator](/docs/navigators) instead)
```js
class MyNavigator extends React.Component {
static router = 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`.
```js
const MyApp = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
const defaultGetStateForAction = MyApp.router.getStateForAction;
MyApp.router.getStateForAction = (action, state) => {
if (state && action.type === 'PushTwoProfiles') {
const routes = [
...state.routes,
{key: 'A', routeName: 'Profile', params: { name: action.name1 }},
{key: 'B', routeName: 'Profile', params: { name: action.name2 }},
];
return {
...state,
routes,
index: routes.length - 1,
};
}
return defaultGetStateForAction(action, state);
};
```
### Blocking Navigation Actions
Sometimes you may want to prevent some navigation activity, depending on your route.
```js
import { NavigationActions } from 'react-navigation'
const MyStackRouter = StackRouter({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
const defaultGetStateForAction = MyStackRouter.router.getStateForAction;
MyStackRouter.router.getStateForAction = (action, state) => {
if (
state &&
action.type === NavigationActions.BACK &&
state.routes[state.index].params.isEditing
) {
// Returning null from getStateForAction means that the action
// has been handled/blocked, but there is not a new state
return null;
}
return defaultGetStateForAction(action, state);
};
```
### Handling Custom URIs
Perhaps your app has a unique URI which the built-in routers cannot handle. You can always extend the router `getActionForPathAndParams`.
```js
import { NavigationActions } from 'react-navigation'
const MyApp = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
const previousGetActionForPathAndParams = MyApp.router.getActionForPathAndParams;
Object.assign(MyApp.router, {
getActionForPathAndParams(path, params) {
if (
path === 'my/custom/path' &&
params.magic === 'yes'
) {
// returns a profile navigate action for /my/custom/path?magic=yes
return NavigationActions.navigate({
routeName: 'Profile',
action: NavigationActions.navigate({
// This child action will get passed to the child router
// ProfileScreen.router.getStateForAction to get the child
// navigation state.
routeName: 'Friends',
}),
});
}
return previousGetActionForPathAndParams(path, params);
},
});
```

View File

@@ -1,103 +0,0 @@
## Custom Router API
You can make your own router by building an object with the following functions:
```js
const MyRouter = {
getStateForAction: (action, state) => ({}),
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:
class MyNavigator extends React.Component {
static router = MyRouter;
render() {
...
}
}
```
![Routers manage the relationship between URIs, actions, and navigation state](/assets/routers-concept-map.png)
### `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`.
### `getComponentForRouteName(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.getComponentForRouteName('Foo')` or `router.getComponentForRouteName('Bar')`.
### `getComponentForState(state)`
Returns the active component for a deep navigation state.
### `getActionForPathAndParams(path, params)`
Returns an optional navigation action that should be used when the user navigates to this path and provides optional query parameters.
### `getPathAndParamsForState(state)`
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`.
### `getScreenOptions(navigation, screenProps)`
Used to retrieve the navigation options for a screen. Must provide the screen's current navigation prop and optionally, other props that your navigation options may need to consume.
- `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.
- `screenProps` - Other props that your navigation options may need to consume
- `navigationOptions` - The previous set of options that are default or provided by the previous configurer
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.
const screenNavigation = addNavigationHelpers({
// In this case we use navigation.state.index because we want the title for the active route.
state: navigation.state.routes[navigation.state.index],
dispatch: navigation.dispatch,
});
const options = this.props.router.getScreenOptions(screenNavigation, {});
const title = options.title;
```

View File

@@ -1,64 +0,0 @@
# StackRouter
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
const MyApp = StackRouter({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
```
### RouteConfig
A basic stack router expects a route config object. Here is an example configuration:
```js
const MyApp = 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.
- `initialRouteName` - 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.

View File

@@ -1,60 +0,0 @@
# TabRouter
Manage a set of tabs in the application, handle jumping to tabs, and handle the back button press to jump to the initial tab.
Let's take a look at a simple tabs router:
```js
const MyApp = TabRouter({
Home: { screen: HomeScreen },
Settings: { screen: SettingsScreen },
}, {
initialRouteName: 'Home',
})
```
### RouteConfig
A tabs router has a routeConfig for each possible tab:
```js
const MyApp = TabRouter({ // This is the RouteConfig:
Home: {
screen: HomeScreen,
path: 'main',
},
Settings: {
// This can be handy to lazily require a tab:
getScreen: () => require('./SettingsScreen').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 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.

View File

@@ -1,195 +0,0 @@
# Transitioner
`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
class MyNavView extends Component {
...
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.
#### Examples
```js
_configureTransition(transitionProps, prevTransitionProps) {
return {
// duration in milliseconds, default: 250
duration: 500,
// 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:
```js
_configureTransition(transitionProps, prevTransitionProps) {
return {
// A timing function, default: Animated.timing.
timing: Animated.spring,
// Some parameters relevant to Animated.spring
friction: 1,
tension: 0.5,
}
}
```
#### Flow definition
```js
configureTransition: (
transitionProps: NavigationTransitionProps,
prevTransitionProps: ?NavigationTransitionProps,
) => NavigationTransitionSpec,
```
#### Parameters
- `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
### `navigation` prop
An object with `state` that represents the navigation state, with `routes` and an active route `index`. Also includes `dispatch` and other methods for requesting actions.
#### Example value
```js
{
// Index refers to the active child route in the routes array.
index: 1,
routes: [
{ key: 'DF2FGWGAS-12', routeName: 'ContactHome' },
{ key: 'DF2FGWGAS-13', routeName: 'ContactDetail', params: { personId: 123 } }
]
}
```
#### Flow definition
```js
export type NavigationState = {
index: number,
routes: Array<NavigationRoute>,
};
```
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 numeric 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:
```jsx
_render(transitionProps, prevTransitionProps) {
const scenes = transitionProps.scenes.map(scene => this._renderScene(transitionProps, scene));
return (
<View style={styles.stack}>
{scenes}
</View>
);
}
```
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;
const opacity = position.interpolate({
inputRange: [index-1, index, index+1],
outputRange: [0, 1, 0],
});
// The prop `router` is populated when we call `createNavigator`.
const Scene = this.props.router.getComponent(scene.route.routeName);
return (
<Animated.View style={{ opacity }}>
{ Scene }
</Animated.View>
)
}
```
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).
#### Flow definition
```js
render: (transitionProps: NavigationTransitionProps, prevTransitionProps: ?NavigationTransitionProps) => React.Node,
```
#### Parameters
- `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.
If you return a promise from `onTransitionStart`, the transition animation will begin after the promise is resolved.
#### Flow definition
```js
onTransitionStart: (transitionProps: NavigationTransitionProps, prevTransitionProps: ?NavigationTransitionProps) => (Promise | void),
```
#### Parameters
- `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
- `Promise` to delay the start of the transition animation, or none to begin the transition animation immediately.
### `onTransitionEnd` function
Invoked once the transition animation completes.
If you return a promise from `onTransitionEnd`, any queued transition animations will begin after the promise is resolved.
#### Flow definition
```js
onTransitionEnd: () => void
```
#### Parameters
- none.
#### Returns
- none.

View File

@@ -1,18 +0,0 @@
# Views
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/CardStack.js) - Present a stack that looks suitable on any platform
+ [Card](https://github.com/react-community/react-navigation/blob/master/src/views/CardStack/Card.js) - Present one card from the card stack, with gestures
+ [Header](https://github.com/react-community/react-navigation/blob/master/src/views/Header/Header.js) - The header view for the card stack
- [Tabs](https://github.com/react-community/react-navigation/blob/master/src/views/TabView/TabView.js) - A configurable tab switcher / pager
- [Drawer](https://github.com/react-community/react-navigation/blob/master/src/views/Drawer/DrawerView.js) - 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)

View File

@@ -1,25 +0,0 @@
# withNavigation
[`withNavigation`](/src/views/withNavigation.js) is a Higher Order Component which passes the `navigation` prop into a wrapped Component. It's useful when you cannot pass the `navigation` prop 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';
const MyComponent = ({ to, navigation }) => (
<Button title={`navigate to ${to}`} onPress={() => navigation.navigate(to)} />
);
const MyComponentWithNavigation = withNavigation(MyComponent);
// or use decorators:
@withNavigation
export default class MainScreen extends Component {
...
}
```

View File

@@ -1,62 +0,0 @@
# Introducing React Navigation for React Native
_January 26, 2017_
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
const MyApp = StackNavigator({
Home: {screen: HomeScreen},
Profile: {screen: ProfileScreen},
});
```
Each of these screens are just React components, and they can easily set their own title:
```js
class HomeScreen extends React.Component {
static navigationOptions = {
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!

View File

@@ -1,13 +0,0 @@
# On the path to React Navigation v1
*April 26, 2017*
When we announced React Navigation earlier this year, the core team was blown away at the community's overwhelming excitement and support for the new project. Since the launch in late January, hundreds of contributors have sprung up, reported detailed issues, and committed important fixes to the library.
With several community members preparing to put apps in production, the highest priority for the core team is to refine the final v1 API, and stabilize it to make sure your apps feel rock-soild.
Today we're excited to announce the release of [beta 9](https://github.com/react-community/react-navigation/releases/tag/v1.0.0-beta.9), which iterates upon the initial API. Although you will need to modify your screen navigation options for this upgrade, we are very confident in the new API. Our goal for future v1 releases is to avoid making any breaking API changes - we are now focused on filling in essential missing features, and stabilization.
The community has experienced some thrash by a few of our earlier beta releases. So, starting with [this release](https://github.com/react-community/react-navigation/releases/tag/v1.0.0-beta.9), we will include detailed [release notes](https://github.com/react-community/react-navigation/releases) about any API changes, new features, and bug fixes.
After the stabilization and release of v1, we're excited to explore new ways of customizing transitions, and overriding navigation components. There are some [exciting proposals](https://github.com/react-community/react-navigation/issues/1263) about these new APIs, and we look forward to the community's feedback and involvement.

View File

@@ -1,71 +0,0 @@
# A (Renewed) Path to React Navigation V1
*September 12, 2017*
Its been awhile since the last post on this blog and I wanted to take a moment to bring everyone up to speed on whats been going on with React Navigation.
This project got big really fast: as the officially recommended navigation library for React Native, thousands of developers are using the project every day to build apps.
Having such a broad usage, the repository has a lot of new questions, feature requests, and (as with any library) bugs. Its gotten a bit out of hand (thus hard to manage) so I wanted to give you an overview of how were trying to get things moving forward again resulting in a stable V1 release.
## Issues
If you've looked at the project over the last few months you've probably seen that there are a lot of open issues. If you've looked closely over the last few weeks you may have noticed that it's a few hundred less - [progress](https://github.com/react-community/react-navigation/pulse/monthly)!
I wanted to tell you about how were addressing the GitHub issues: in an effort to reduce the cognitive load associated with so many open issues we've set out to accomplish a few things:
1. Label all issues
2. Close any "question" type issues. The idea here is to keep GitHub issues focused on bugs & feature requests. [StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation) and [Reactiflux](https://www.reactiflux.com/) are better places for questions.
3. Eliminate duplicate issues
4. Of the remaining issues determine bugs & features necessary for V1
Don't hesitate to open new issues but **please do follow** the issue template! 😄
## Pull Requests
We greatly appreciate all the time put into each and every one of them but, as with issues, there's a bit of a backlog to work through.
We encourage PRs but we want you to know that were prioritizing bug fixes and feature requests that align with the new 1.0 roadmap (see next section). We want to focus on the highest impact features for the community as a whole.
## A New Roadmap
Were happy to say weve put together a new roadmap to version 1.0 of this package! You can see what will be included by checking out [this issue](https://github.com/react-community/react-navigation/issues/2585).
How do we decide on what to include in the revised V1.0?
We had conversations with people using React Navigation in production, looked at issues with the most reactions, reviewed high quality pull requests, and talked with the community to see what was needed.
Will V1.0 cover everyones uses? No. But it should cover most use cases and we hope to improve documentation enough that youre comfortable and able to customize React Navigation to your needs.
## Roles & Responsibilities
Just like any other organization - no one person can do everything. Its helpful to have defined roles & responsibilities so that others know who to ask and we can avoid becoming overwhelmed.
This is something I want to adopt for the management of React Navigation. I hope it reduces the likelihood of burnout for those that have chosen to dedicate time to the project. With that in mind here are the roles a few primary contributors have chosen to take on:
- [davepack](https://github.com/davepack) - Pull request review, development
- [GantMan](https://github.com/GantMan) - Issue management, testing
- [kelset](https://github.com/kelset) - Issue management, pull request review
- [matthamil](https://github.com/matthamil) - Pull request review, issue management
- [skevy](https://github.com/skevy) - Pull request review, release management
- [spencercarli](https://github.com/spencercarli) - Documentation, issue management
[Expo](https://expo.io/) has expressed that React Navigation V1.0 is a priority for them and has committed one of their engineers (Dave) to aid in that.
## The Community Navigation Library
React Navigation is the React Native communitys navigation library with that being said - you too can contribute!
If you see someone's question - try to answer it!
If you have thoughts on a potential API for a requested feature - share it!
If you think you know the cause for a bug - explain it!
Regardless of what you do though, be nice & remember that on the other side of the screen there is another developer, just like you…
Personally, I [enjoy some shade](https://media.giphy.com/media/l4FGlDsvuUd2RkBYQ/giphy.gif) thrown my way, but I might be in the minority 😉.
Thanks for reading and I look forward to working with you on React Navigation!
Spencer Carli
*Thanks to Matt Hamill & Lorenzo Sciandra for reviewing.*

View File

@@ -1,229 +0,0 @@
# Common Navigation Spec
### Introduction
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:
```javascript
type BackAction = {type: 'Navigation/BACK'};
type URIAction = {type: 'Navigation/URI', uri: string};
interface Navigation<S, A> {
dispatch(action: (A | BackAction | URIAction)): boolean;
state: S;
}
```
#### navigation.state
The controlled navigation state prop, as requested by the parent.
```javascript
const MyView = ({ 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
const MyLink = ({ navigation }) => (
<Button onPress={() => {
navigation.dispatch({
type: 'MyNavigationRequest',
myParam: 42,
});
}>
Press me to navigate
</Button>
);
```
### The static `router`
A router object may be statically defined on your component. If defined, it must follow this interface:
```javascript
type BackAction = {type: 'Navigation/BACK'};
type URIAction = {type: 'Navigation/URI', uri: string};
interface Router<S, A> {
getStateForAction(action: (A | BackAction | URIAction), lastState: ?S): ?S;
getActionForURI(uri: string): ?A;
}
```
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
class ScreenWithEditMode extends React.Component {
static router = {
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.
### "Link deeply into one screen of my app"
```
class Foo extends React.Component {
static router = {
getStateForAction(action, prevState = {deep: false}) {
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

View File

@@ -1,94 +0,0 @@
# Custom Navigators
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
class MyNavigator extends React.Component {
static router = 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:
const Component = MyRouter.getComponentForState(state);
// The state of the active child screen can be found at routes[index]
let childNavigation = { dispatch, state: routes[index] };
// If we want, we can also tinker with the dispatch function here, to limit
// or augment our children's actions
// Assuming our children want the convenience of calling .navigate() and so on,
// we should call addNavigationHelpers to augment our navigation prop:
childNavigation = addNavigationHelpers(childNavigation);
return <Component navigation={childNavigation} />;
}
}
```
## Navigation Prop
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`.
## 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
const MyApp = createNavigator(MyRouter)(MyView);
```
All this does behind the scenes is:
```js
const MyApp = ({ navigation }) => (
<MyView router={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.

View File

@@ -1,53 +0,0 @@
## Customizing Navigation Views
Modify the presentation of navigation, including styles, animations and gestures.
## Customizing Routers
Building a custom router allows you to change the navigation logic of your component, manage navigation state, and define behavior for URIs.
A router can be defined like this:
```js
class MyNavigationAwareComponent extends React.Component {
static router = {
// Defines the navigation state for a component:
getStateForAction: (action: {type: string}, lastState?: any) => {
const state = lastState = { myMode: 'default' };
if (action.type === 'MyAction') {
return { myMode: 'action' };
} else if (action.type === NavigationActions.BACK) {
return { myMode: 'blockBackButton' };
} else {
return state;
}
},
// Defines if a component can handle a particular URI.
// If it does, return an action to be passed to `getStateForAction`
getActionForURI: (uri: string) => {
if (uri === 'myapp://myAction') {
return { type: 'MyAction' };
}
return null;
},
};
render() {
// render something based on this.props.navigation.state
...
}
onButtonPress = () => {
this.props.navigation.dispatch({ type: 'MyAction' });
};
...
}
```

View File

@@ -1,111 +0,0 @@
# Deep Linking
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
const SimpleApp = 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
const SimpleApp = 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.
```js
const SimpleApp = StackNavigator({...});
// on Android, the URI prefix typically contains a host in addition to scheme
const prefix = Platform.OS == 'android' ? 'mychat://mychat/' : 'mychat://';
const MainApp = () => <SimpleApp uriPrefix={prefix} />;
```
## iOS
Let's configure the native iOS app to open based on the `mychat://` URI scheme.
In `SimpleApp/ios/SimpleApp/AppDelegate.m`:
```
// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>
// Add this above the `@end`:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
}
```
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.
![Xcode project info URL types with mychat added](/assets/xcode-linking.png)
Now you can press play in Xcode, or re-build on the command line:
```sh
react-native run-ios
```
To test the URI on the simulator, run the following:
```
xcrun simctl openurl booted mychat://chat/Taylor
```
To test the URI on a real device, 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:
```
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mychat"
android:host="mychat" />
</intent-filter>
```
Now, re-install the app:
```sh
react-native run-android
```
To test the intent handling in Android, run the following:
```
adb shell am start -W -a android.intent.action.VIEW -d "mychat://mychat/chat/Taylor" com.simpleapp
```
```phone-example
linking
```

View File

@@ -1,235 +0,0 @@
# Hello Mobile Navigation
Let's use React Navigation to build a simple chat-like 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
```
If you are using `create-react-native-app` instead of `react-native init`, then:
```sh
# Create a new React Native App
create-react-native-app SimpleApp
cd SimpleApp
# Install the latest version of react-navigation from npm
npm install --save react-navigation
# Run the new app
npm start
# This will start a development server for you and print a QR code in your terminal.
```
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 let's delete the contents of `index.js` (or `index.ios.js` and `index.android.js` if using a React Native version before 0.49) and replace it with `import './App';` - after which, we need to create the new file for our app implementation, `App.js` (if you used `create-react-native-app` this has been already done)
## Introducing Stack Navigator
For our app, we want to use the `StackNavigator` because conceptually we want to obtain a 'card stack' effect of movement, where each new screen is put on the top of the stack and going back removes a screen from the top of the stack. Let's start with just one screen:
```js
import React from 'react';
import {
AppRegistry,
Text,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
export const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
});
AppRegistry.registerComponent('SimpleApp', () => SimpleApp);
```
If you used `create-react-native-app` the already existing `App.js` will be modified to
```js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome'
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen }
});
export default class App extends React.Component {
render() {
return <SimpleApp />;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
});
```
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
In our `App.js` file, let's add a new screen called `ChatScreen`, defining it under `HomeScreen`:
```js
// ...
class HomeScreen extends React.Component {
//...
}
class ChatScreen extends React.Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text>Chat with Lucy</Text>
</View>
);
}
}
```
We can then add a button to our `HomeScreen` component that links to `ChatScreen`: we need to use the provided method `navigate` (from the [screen navigation prop](/docs/navigators/navigation-prop)) by giving it the `routeName` of the screen we want to reach, in this case `Chat`.
```js
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
```
(*don't forget to import View and Button from react-native:* `import { AppRegistry, Text, View, Button } from 'react-native';`)
But that won't work until we say to our `StackNavigator` of the existence of the `Chat` screen, like so:
```js
export const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});
```
Now you can navigate to your new screen, and go back:
```phone-example
first-navigation
```
## Passing params
Hardcoding a name into the `ChatScreen` isn't ideal. It'd be more useful if we could pass a name to be rendered instead, so let's do that.
In addition to specifying the target `routeName` in the navigate function, we can pass params that will be put into the new route. First, we'll edit our `HomeScreen` component to pass a `user` param into the route.
```js
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat', { user: 'Lucy' })}
title="Chat with Lucy"
/>
</View>
);
}
}
```
We can then edit our `ChatScreen` component to display the `user` param that was passed in through the route:
```js
class ChatScreen extends React.Component {
// Nav options can be defined as a function of the screen's props:
static navigationOptions = ({ navigation }) => ({
title: `Chat with ${navigation.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>
);
}
}
```
Now you can see the name when you navigate to the Chat screen. Try changing the `user` param in `HomeScreen` and see what happens!
```phone-example
first-navigation
```

View File

@@ -1,140 +0,0 @@
# Configuring the Header
Header is only available for StackNavigator.
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:
```js
this.props.navigation.navigate('Chat', { user: 'Lucy' });
```
The `user` param can be accessed from the chat screen:
```js
class ChatScreen extends React.Component {
render() {
const { params } = this.props.navigation.state;
return <Text>Chat with {params.user}</Text>;
}
}
```
### Setting the Header Title
Next, the header title can be configured to use the screen param:
```js
class ChatScreen extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: `Chat with ${navigation.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 = {
headerRight: <Button title="Info" />,
...
```
```phone-example
header-button
```
The navigation options can be defined with a [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 = ({ navigation }) => {
const { state, setParams } = navigation;
const isInfo = state.params.mode === 'info';
const { user } = state.params;
return {
title: isInfo ? `${user}'s Contact Info` : `Chat with ${state.params.user}`,
headerRight: (
<Button
title={isInfo ? 'Done' : `${user}'s info`}
onPress={() => setParams({ mode: isInfo ? 'none' : 'info' })}
/>
),
};
};
```
Now, the header can interact with the screen route/state:
```phone-example
header-interaction
```
### Header interaction with screen component
Sometimes it is necessary for the header to access properties of the screen component such as functions or state.
Let's say we want to create an 'edit contact info' screen with a save button in the header. We want the save button to be replaced by an `ActivityIndicator` while saving.
```js
class EditInfoScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
let headerRight = (
<Button
title="Save"
onPress={params.handleSave ? params.handleSave : () => null}
/>
);
if (params.isSaving) {
headerRight = <ActivityIndicator />;
}
return { headerRight };
};
state = {
nickname: 'Lucy jacuzzi'
}
_handleSave = () => {
// Update state, show ActivityIndicator
this.props.navigation.setParams({ isSaving: true });
// Fictional function to save information in a store somewhere
saveInfo().then(() => {
this.props.navigation.setParams({ isSaving: false});
})
}
componentDidMount() {
// We can only set the function after the component has been initialized
this.props.navigation.setParams({ handleSave: this._handleSave });
}
render() {
return (
<TextInput
onChangeText={(nickname) => this.setState({ nickname })}
placeholder={'Nickname'}
value={this.state.nickname}
/>
);
}
}
```
**Note**: Since the `handleSave`-param is only set on component mount it is not immediately available in the `navigationOptions`-function. Before `handleSave` is set we pass down an empty function to the `Button`-component in order to make it render immediately and avoid flickering.
To see the rest of the header options, see the [navigation options document](/docs/navigators/navigation-options#Stack-Navigation-Options).
As an alternative to `setParams`, you may want to consider using a state management library such as [MobX](https://github.com/mobxjs/mobx) or [Redux](https://github.com/reactjs/redux), and when navigating to a screen, pass an object which contains the data necessary for the screen to render, as well as functions you may want to call that modify the data, make network requests and etc. That way, both your screen component and the static `navbarOptions` block will have access to the object. When following this approach, make sure to consider deep linking, which works best in cases where only javascript primitives are passed as navigation props to your screen. In case when deep linking is necessary, you may use a [higher order component (HOC)](https://reactjs.org/docs/higher-order-components.html) to transform the primitives to the object your screen components expects.

View File

@@ -1,23 +0,0 @@
# Introduction
_Learn once, navigate anywhere._
React Navigation is born from the React Native community's need for an extensible yet easy-to-use navigation solution based on Javascript.
React Navigation is the result of a collaboration between developers from Facebook, Expo and the React community at large: it replaces and improves upon several navigation libraries in the ecosystem, including Ex-Navigation, React Native's Navigator and NavigationExperimental components.
## Getting Started
If you're already familiar with React Native then you'll be able to get moving with React Navigation in minimal time.
1. [Quick Start](/docs/intro/quick-start)
Quickly get a grasp on the React Navigation API with demonstrations of the StackNavigator, TabNavigator, and DrawerNavigator.
2. [Simple App](/docs/intro/basic-app)
Dive into the basics of React Navigation by creating a new React Native project, installing React Navigation, creating your first navigator, and learning how to interact with it.
3. [Navigation Playground](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground)
Curious of the various capabilities of React Navigation? Browse the official example app, which will demonstrate various patterns with React Navigation.
4. [Community Contributions](https://github.com/react-community/react-navigation#community-contributions)
With the flexibility of React Navigation we won't be able to cover every possible situation, but another developer may have! Browse our list of community contributions to find topics that may answer your questions.

View File

@@ -1,122 +0,0 @@
# Nesting Navigators
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
import { TabNavigator } from "react-navigation";
class RecentChatsScreen extends React.Component {
render() {
return <Text>List of recent chats</Text>
}
}
class AllContactsScreen extends React.Component {
render() {
return <Text>List of all contacts</Text>
}
}
const MainScreenNavigator = 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
const SimpleApp = StackNavigator({
Home: {
screen: MainScreenNavigator,
navigationOptions: {
title: 'My Chats',
},
},
Chat: { screen: ChatScreen },
})
```
Lets also add a button to each tab that links to a chat:
```js
<Button
onPress={() => this.props.navigation.navigate('Chat', { user: 'Lucy' })}
title="Chat with Lucy"
/>
```
Now we have put one navigator inside another, and we can `navigate` between navigators:
```phone-example
nested
```
## Nesting a Navigator in a Component
Sometimes it is desirable to nest a navigator that is wrapped in a component. This is useful in cases where the navigator only takes up part of the screen. For the child navigator to be wired into the navigation tree, it needs the `navigation` property from the parent navigator.
```js
const SimpleApp = StackNavigator({
Home: { screen: NavigatorWrappingScreen },
Chat: { screen: ChatScreen },
});
```
In this case, the NavigatorWrappingScreen is not a navigator, but it renders a navigator as part of its output.
If this navigator renders blank then change `<View>` to `<View style={{flex: 1}}>`.
```js
class NavigatorWrappingScreen extends React.Component {
render() {
return (
<View>
<SomeComponent/>
<MainScreenNavigator/>
</View>
);
}
}
```
To wire `MainScreenNavigator` into the navigation tree, we assign its `router` to the wrapping component. This makes `NavigatorWrappingScreen` "navigation aware", which tells the parent navigator to pass the navigation object down. Since the `NavigatorWrappingScreen`'s `router` is overridden with the child navigator's `router`, the child navigator will receive the needed `navigation`.
```js
class NavigatorWrappingScreen extends React.Component {
render() {
return (
<View>
<SomeComponent/>
<MainScreenNavigator navigation={this.props.navigation}/>
</View>
);
}
}
NavigatorWrappingScreen.router = MainScreenNavigator.router;
```

View File

@@ -1,316 +0,0 @@
# Quick Start Guide
To get started with React Navigation, all you have to do is install the `react-navigation` npm package.
### Install with NPM
```
npm install --save react-navigation
```
### Install with Yarn
```
yarn add react-navigation
```
To start using React Navigation you'll have to create a navigator. React Navigation comes with three default navigators.
- `StackNavigator` - Provides a way for your app to transition between screens where each new screen is placed on top of a stack.
- `TabNavigator` - Used to set up a screen with several tabs.
- `DrawerNavigator` - Used to set up a screen with drawer navigation.
## Creating a StackNavigator
StackNavigator's are the most common form of navigator so we'll use it as a basic demonstration. To get started, create a `StackNavigator`.
```javascript
import { StackNavigator } from 'react-navigation';
const RootNavigator = StackNavigator({
});
export default RootNavigator;
```
We can then add screens to this `StackNavigator`. Each key represents a screen.
```javascript
import React from 'react';
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
const HomeScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
const DetailsScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
const RootNavigator = StackNavigator({
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
});
export default RootNavigator;
```
Now let's add a title to the navigation bar.
```javascript
...
const RootNavigator = StackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
headerTitle: 'Home',
},
},
Details: {
screen: DetailsScreen,
navigationOptions: {
headerTitle: 'Details',
},
},
});
export default RootNavigator;
```
Finally, we should be able to navigate from the home screen to the details screen. When you register a component with a navigator that component will then have a `navigation` prop added to it. This `navigation` prop drives how we move between different screens.
To move from the home screen to the details screen we'll want to use `navigation.navigate`, like so:
```javascript
...
import { View, Text, Button } from 'react-native';
const HomeScreen = ({ navigation }) => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
onPress={() => navigation.navigate('Details')}
title="Go to details"
/>
</View>
);
...
```
And there you have it! That's the basics of using the [StackNavigator](/docs/navigators/stack), and React Navigation as a whole. Here's the full code from this example:
<div class="snack" data-snack-id="HJlnU0XTb" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.16);border-radius:4px;height:505px;width:100%"></div>
## Creating a TabNavigator
To get started with `TabNavigator` first import and create a new `RootTabs` component.
```javascript
import { TabNavigator } from 'react-navigation';
const RootTabs = TabNavigator({
});
export default RootTabs;
```
We then need to create some screens and add them to our `TabNavigator`.
```javascript
import React from 'react';
import { View, Text } from 'react-native';
import { TabNavigator } from 'react-navigation';
const HomeScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
const ProfileScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
</View>
);
const RootTabs = TabNavigator({
Home: {
screen: HomeScreen,
},
Profile: {
screen: ProfileScreen,
},
});
export default RootTabs;
```
Getting there! Now let's explicity set a label and icon for the tab bar.
> We'll be using [`react-native-vector-icons`](https://github.com/oblador/react-native-vector-icons) in the example. If you don't have it installed in your project already please do so.
```javascript
...
import Ionicons from 'react-native-vector-icons/Ionicons';
...
const RootTabs = TabNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarLabel: 'Profile',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-person' : 'ios-person-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
});
export default RootTabs;
```
This will ensure the `tabBarLabel` is consistent (important when using nested navigators) and it will set a `tabBarIcon`. This icon will only be visible on iOS by default given the tab bar component used, which aligns with standard design patterns on Android.
You can view the complete finished code below:
<div class="snack" data-snack-id="BJZ2GVVpb" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.16);border-radius:4px;height:505px;width:100%"></div>
## Creating a DrawerNavigator
To get started with `DrawerNavigator` first import and create a new `RootDrawer` component.
```javascript
import { DrawerNavigator } from 'react-navigation';
const RootDrawer = DrawerNavigator({
});
export default RootDrawer;
```
We then need to create some screens and add them to our `DrawerNavigator`.
```javascript
import React from 'react';
import { View, Text } from 'react-native';
import { DrawerNavigator } from 'react-navigation';
const HomeScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
const ProfileScreen = () => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
</View>
);
const RootDrawer = DrawerNavigator({
Home: {
screen: HomeScreen,
},
Profile: {
screen: ProfileScreen,
},
});
export default RootDrawer;
```
Getting there! Now let's explicity set a label and icon for the drawer items.
> We'll be using `react-native-vector-icons` in the example. If you don't have it installed in your project already please do so.
```javascript
...
import Ionicons from 'react-native-vector-icons/Ionicons';
...
const RootDrawer = DrawerNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={20}
style={{ color: tintColor }}
/>
),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
drawerLabel: 'Profile',
drawerIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-person' : 'ios-person-outline'}
size={20}
style={{ color: tintColor }}
/>
),
},
},
});
export default RootDrawer;
```
To open the drawer you can swipe from the left edge of the screen to the right. You've also got the option to open the drawer view `navigation.navigate('DrawerToggle')`, which we'll add to the Home component now. Make sure you import the `Button` component from `react-native`.
```javascript
...
const HomeScreen = ({ navigation }) => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
onPress={() => navigation.navigate('DrawerToggle')}
title="Open Drawer"
/>
</View>
);
...
```
You can view the finished code below.
<div class="snack" data-snack-id="rk90N44a-" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.16);border-radius:4px;height:505px;width:100%"></div>

View File

@@ -1,174 +0,0 @@
## 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:
```
const HybridNavigationModule = require('NativeModules').HybridNavigation;
HybridNavigationModule.registerScreens([
{
type: 'Marketplace',
screen: MarketplaceScreen,
},
{
type: 'Product',
screen: ProductScreen,
},
]);
```
## Linking to JS
Now, your native code can open a react screen by type name:
```
// please pretend this is Obj-C or Java syntax:
CoreHybridNavigation.openReactScreen('Profile', {id: 123});
```
## Linking to Native
If JS product code wants to request navigation to a screen that may *or may not* be in native, it can do this:
```
const MarketplaceScreen = ({ navigation }) => (
<View>
<Button onPress={() => navigation.dispatch({
type: 'Product',
id: 42,
})}>
See product 42
</Button>
</View>
);
```
Inside the infra:
```
class InfraScreen extends React.Component {
constructor() {
const {initURI, type} = this.props;
const ScreenView = ScreenRegistry[type].screen;
const router = ScreenView.router;
const deepLinkAction = router.getActionForURI(initURI);
const initAction = deepLinkAction || {type: 'init'}
const nav = router.getStateForAction(initAction);
this.state = {
nav,
};
HybridNavigationModule.setNavOptions(this.state.nav);
}
componentWillUpdate() {
HybridNavigationModule.setNavOptions(this.state.nav);
}
dispatch = (action) => {
const {type} = this.props;
const ScreenView = ScreenRegistry[type].screen;
const {getStateForAction} = ScreenView.router;
const newNavState = getStateForAction(action, this.state.nav);
if (newNavState !== this.state.nav) {
this.setState({ nav: newNavState });
return true;
}
if (action.type === 'URI') {
HybridNavigationModule.openURI(action.uri);
return true;
}
if (action.type === NavigationActions.BACK) {
HybridNavigationModule.goBack();
return true;
}
HybridNavigationModule.openAction(action);
return true;
}
render() {
const {type} = this.props;
const ScreenView = ScreenRegistry[type].screen;
const navigation = {
dispatch: this.dispatch,
state: this.state.nav,
};
return <ScreenView navigation={navigation} />;
}
}
```
## Setting title
```
MarketplaceScreen.router = {
getStateForAction(action, lastState) {
return lastState || {title: 'Marketplace Home'};
},
};
```
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.

View File

@@ -1,111 +0,0 @@
# Navigation Actions
All Navigation Actions return an object that can be sent to the router using `navigation.dispatch()` method.
Note that if you want to dispatch react-navigation actions you should use the action creators provided in this library.
The following actions are supported:
* [Navigate](#Navigate) - Navigate to another route
* [Reset](#reset) - Replace current state with a new state
* [Back](#Back) - Go back to previous state
* [Set Params](#SetParams) - Set Params for given route
* [Init](#Init) - Used to initialize first state if state is undefined
The action creator functions define `toString()` to return the action type, which enables easy usage with third-party Redux libraries, including redux-actions and redux-saga.
### Navigate
The `Navigate` action will update the current state with the result of a `Navigate` action.
- `routeName` - *String* - Required - A destination routeName that has been registered somewhere in the app's router
- `params` - *Object* - Optional - Params to merge into the destination route
- `action` - *Object* - Optional - (advanced) The sub-action to run in the child router, if the screen is a navigator. Any one of the actions described in this doc can be set as a sub-action.
```js
import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
```
### Reset
The `Reset` action wipes the whole navigation state and replaces it with the result of several actions.
- `index` - *number* - required - Index of the active route on `routes` array in navigation `state`.
- `actions` - *array* - required - Array of Navigation Actions that will replace the navigation state.
- `key` - *string or null* - optional - If set, the navigator with the given key will reset. If null, the root navigator will reset.
```js
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Profile'})
]
})
this.props.navigation.dispatch(resetAction)
```
#### How to use the `index` parameter
The `index` param is used to specify the current active route.
eg: given a basic stack navigation with two routes `Profile` and `Settings`.
To reset the state to a point where the active screen was `Settings` but have it stacked on top of a `Profile` screen, you would do the following:
```js
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'Profile'}),
NavigationActions.navigate({ routeName: 'Settings'})
]
})
this.props.navigation.dispatch(resetAction)
```
### Back
Go back to previous screen and close current screen. `back` action creator takes in one optional parameter:
- `key` - *string or null* - optional - If set, navigation will go back from the given key. If null, navigation will go back anywhere.
```js
import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back({
key: 'Profile'
})
this.props.navigation.dispatch(backAction)
```
### SetParams
When dispatching `SetParams`, the router will produce a new state that has changed the params of a particular route, as identified by the key
- `params` - *object* - required - New params to be merged into existing route params
- `key` - *string* - required - Route key that should get the new params
```js
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
```

View File

@@ -1,137 +0,0 @@
# Redux Integration
### Overview For Redux Integration
1. To handle your app's navigation state in redux, you can pass your own `navigation` prop to a navigator.
2. Once you pass your own navigation prop to the navigator, the default [`navigation`](https://reactnavigation.org/docs/navigators/navigation-prop) prop gets destroyed. You will most probably pass the `navigation` prop's properties that you want to access. Normally [`state`](https://reactnavigation.org/docs/navigators/navigation-prop#state-The-screen's-current-stateroute) and [`dispatch`](https://reactnavigation.org/docs/navigators/navigation-prop#dispatch-Send-an-action-to-the-router) properties are passed to the navigator. You will learn how to pass those properties further in this guide. Since you have destroyed the default props, if you try to invoke something you have not explicitly passed down, it won't work. So, if you didn't pass `dispatch` to the navigator and only passes `state` than you can't access `dispatch` further in your Components.
3. The `state` will be fed from the reducer assigned to handle navigation state and the `dispatch` will be redux's default `dispatch`. Thus you will be able to dispatch normal redux actions using `this.props.navigation.dispatch(ACTION)`, reducer will update the navigation state on the basis of dispatched action, the new navigation state will then be passed to the navigator.
### Details Regarding Redux Integration
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:
```es6
import { addNavigationHelpers } from 'react-navigation';
const AppNavigator = StackNavigator(AppRouteConfigs);
const initialState = AppNavigator.router.getStateForAction(AppNavigator.router.getActionForPathAndParams('Login'));
const navReducer = (state = initialState, action) => {
const nextState = AppNavigator.router.getStateForAction(action, state);
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state;
};
const appReducer = combineReducers({
nav: navReducer,
...
});
class App extends React.Component {
render() {
return (
<AppNavigator navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
})} />
);
}
}
const mapStateToProps = (state) => ({
nav: state.nav
});
const AppWithNavigationState = connect(mapStateToProps)(App);
const store = createStore(appReducer);
class Root extends React.Component {
render() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
}
```
Once you do this, your navigation state is stored within your redux store, at which point you can fire navigation actions using your redux dispatch function.
Keep in mind that when a navigator is given a `navigation` prop, it relinquishes control of its internal state. That means you are now responsible for persisting its state, handling any deep linking, [Handling the Hardware Back Button in Android](#Handling-the-Hardware-Back-Button-in-Android), etc.
Navigation state is automatically passed down from one navigator to another when you nest them. Note that in order for a child navigator to receive the state from a parent navigator, it should be defined as a `screen`.
Applying this to the example above, you could instead define `AppNavigator` to contain a nested `TabNavigator` as follows:
```es6
const AppNavigator = StackNavigator({
Home: { screen: MyTabNavigator },
});
```
In this case, once you `connect` `AppNavigator` to Redux as is done in `AppWithNavigationState`, `MyTabNavigator` will automatically have access to navigation state as a `navigation` prop.
## Full example
There's a working example app with redux [here](https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample) if you want to try it out yourself.
## Mocking tests
To make jest tests work with your react-navigation app, you need to change the jest preset in the `package.json`, see [here](https://facebook.github.io/jest/docs/tutorial-react-native.html#transformignorepatterns-customization):
```json
"jest": {
"preset": "react-native",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-navigation)"
]
}
```
## Handling the Hardware Back Button in Android
By using the following snippet, your nav component will be aware of the back button press actions and will correctly interact with your stack. This is really useful on Android.
```es6
import React from "react";
import { BackHandler } from "react-native";
import { addNavigationHelpers, NavigationActions } from "react-navigation";
const AppNavigation = TabNavigator(
{
Home: { screen: HomeScreen },
Settings: { screen: SettingScreen }
}
);
class ReduxNavigation extends React.Component {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { dispatch, nav } = this.props;
if (nav.index === 0) {
return false;
}
dispatch(NavigationActions.back());
return true;
};
render() {
const { dispatch, nav } = this.props;
const navigation = addNavigationHelpers({
dispatch,
state: nav
});
return <AppNavigation navigation={navigation} />;
}
}

View File

@@ -1,104 +0,0 @@
# Screen Navigation Options
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
class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',
};
...
```
**Dynamic Configuration**
Or, the options can be a function that takes the following arguments, and returns an object of navigation options that will override the route-defined and navigator-defined navigationOptions.
- `props` - The same props that are available to the screen component
- `navigation` - The [navigation prop](/docs/navigators/navigation-prop) for the screen, with the screen's route at `navigation.state`
- `screenProps` - The props passing from above the navigator component
- `navigationOptions` - The default or previous options that would be used if new values are not provided
```js
class ProfileScreen extends React.Component {
static navigationOptions = ({ navigation, screenProps }) => ({
title: navigation.state.params.name + "'s Profile!",
headerRight: <Button color={screenProps.tintColor} {...} />,
});
...
```
The screenProps are passed in at render-time. If this screen was hosted in a SimpleApp navigator:
```js
<SimpleApp
screenProps={{tintColor: 'blue'}}
// navigation={{state, dispatch}} // optionally control the app
/>
```
#### 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
class MyScreen extends React.Component {
static navigationOptions = {
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: { screen: RouteOne },
route2: { screen: MyTabNavigator },
});
```
Now, when `route2` is active, you would like to change the tint color of a header. It's easy to do it 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
const MyTabNavigator = TabNavigator({
profile: ProfileScreen,
...
}, {
navigationOptions: {
headerTintColor: 'blue',
},
});
```
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. `headerTintColor`), the screen wins. Therefore, you could change the tint color when `ProfileScreen` is active by doing the following:
```js
class ProfileScreen extends React.Component {
static navigationOptions = {
headerTintColor: 'black',
};
...
}
```
## Navigation Option Reference
List of available navigation options depends on the `navigator` the screen is added to.
Check available options for:
- [`drawer navigator`](/docs/navigators/drawer#Screen-Navigation-Options)
- [`stack navigator`](/docs/navigators/stack#Screen-Navigation-Options)
- [`tab navigator`](/docs/navigators/tab#Screen-Navigation-Options)

View File

@@ -1,159 +0,0 @@
# Screen Navigation Prop
Each *screen* in your app will receive a navigation prop which contain the following:
* `navigate` - (helper) link to other screens
* `state` - screen's current state/routes
* `setParams` - (helper) make changes to route's params
* `goBack` - (helper) close active screen and move back
* `dispatch` - send an action to router
*NOTE:* The `navigation` prop is passed down to every navigation-aware component including navigators. The big exception is that a navigator's `navigation` prop may not have the helper functions (`navigate`, `goBack`, etc); it may only have `state` and `dispatch`. In order to `navigate` using the navigator's `navigation` prop, you will have to `dispatch` using an [action creator](navigation-actions).
*Notes regarding hooking things up with Redux*
> People don't always hook things up to redux correctly, because they mis-understand the navigator's top-level API, where the navigation prop is optional. The navigator will maintain its own state if it doesn't get a navigation prop, but this is not a feature you generally want to use when hooking your app up with redux. For navigators that are nested inside of your main navigator, you always want to pass the screen's navigation prop down. This allows your top-level navigator to communicate and provide state for all the children navigators. Only your top-level router needs to be integrated with redux, because all the other routers are inside it.
## `navigate` - Link to other screens
Call this to link to another screen in your app. Takes the following arguments:
`navigate(routeName, params, action)`
- `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. See [Actions Doc](navigation-actions) for a full list of supported actions.
```js
class HomeScreen extends React.Component {
render() {
const {navigate} = this.props.navigation;
return (
<View>
<Text>This is the home screen of the app</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 return an object with the following:
```js
{
// the name of the route config in the router
routeName: 'profile',
//a unique identifier used to sort routes
key: 'main0',
//an optional object of string options for this screen
params: { hello: 'world' }
}
```
```js
class ProfileScreen extends React.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
class ProfileScreen extends React.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
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);`
```js
class HomeScreen extends React.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>
)
}
}
```
*Going back from a specific screen*
Consider the following navigation stack history:
```...
navigation.navigate(SCREEN_KEY_A);
...
navigation.navigate(SCREEN_KEY_B);
...
navigation.navigate(SCREEN_KEY_C);
...
navigation.navigate(SCREEN_KEY_D);
```
Now you are on *screen D* and want to go back to *screen A* (popping D, C, and B).
Then you need to supply a key to goBack *FROM*:
```
navigation.goBack(SCREEN_KEY_B) // will go to screen A FROM screen B
```
## `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.
See [Navigation Actions Docs](navigation-actions) for a full list of available actions.
```js
import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
// navigate can have a nested navigate action that will be run inside the child router
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
```

View File

@@ -1,93 +0,0 @@
## Screen tracking and analytics
This example shows how to do screen tracking and send to Google Analytics. The approach can be adapted to any other mobile analytics SDK.
### Screen tracking
When using built-in navigation container, we can use `onNavigationStateChange` to track the screen.
```js
import { GoogleAnalyticsTracker } from 'react-native-google-analytics-bridge';
const tracker = new GoogleAnalyticsTracker(GA_TRACKING_ID);
// gets the current screen from navigation state
function getCurrentRouteName(navigationState) {
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getCurrentRouteName(route);
}
return route.routeName;
}
const AppNavigator = StackNavigator(AppRouteConfigs);
export default () => (
<AppNavigator
onNavigationStateChange={(prevState, currentState) => {
const currentScreen = getCurrentRouteName(currentState);
const prevScreen = getCurrentRouteName(prevState);
if (prevScreen !== currentScreen) {
// the line below uses the Google Analytics tracker
// change the tracker here to use other Mobile analytics SDK.
tracker.trackScreenView(currentScreen);
}
}}
/>
);
```
### Screen tracking with Redux
When using Redux, we can write a Redux middleware to track the screen. For this purpose,
we will reuse `getCurrentRouteName` from the previous section.
```js
import { NavigationActions } from 'react-navigation';
import { GoogleAnalyticsTracker } from 'react-native-google-analytics-bridge';
const tracker = new GoogleAnalyticsTracker(GA_TRACKING_ID);
const screenTracking = ({ getState }) => next => (action) => {
if (
action.type !== NavigationActions.NAVIGATE
&& action.type !== NavigationActions.BACK
) {
return next(action);
}
const currentScreen = getCurrentRouteName(getState().navigation);
const result = next(action);
const nextScreen = getCurrentRouteName(getState().navigation);
if (nextScreen !== currentScreen) {
// the line below uses the Google Analytics tracker
// change the tracker here to use other Mobile analytics SDK.
tracker.trackScreenView(nextScreen);
}
return result;
};
export default screenTracking;
```
### Create Redux store and apply the above middleware
The `screenTracking` middleware can be applied to the store during its creation. See [Redux Integration](Redux-Integration.md) for details.
```js
const store = createStore(
combineReducers({
navigation: navigationReducer,
...
}),
applyMiddleware(
screenTracking,
...
),
);
```

View File

@@ -1,16 +0,0 @@
# Web Integration
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.

View File

@@ -1,16 +1,17 @@
{
"presets": ["babel-preset-expo"],
"plugins": [
["module-resolver", {
"alias": {
"react-native": "./node_modules/react-native",
"react": "./node_modules/react"
}
}]
"presets": [
"babel-preset-expo"
],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
"plugins": [
"transform-react-jsx-source"
],
},
"production": {
"plugins": [
"transform-remove-console"
]
}
}
}

View File

@@ -34,28 +34,27 @@
; Ignore react-native-fbads dependency of the expo sdk
.*/node_modules/react-native-fbads/*
.*/react-navigation/lib-rn/.*
.*/react-navigation/lib/.*
.*/react-navigation/examples/ReduxExample/.*
.*/react-navigation/website/.*
; This package is required by Expo and causes Flow errors
.*/node_modules/react-native-gesture-handler/.*
.*/node_modules/metro/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
node_modules/react-native/flow-github/
../../flow/
[options]
module.system=haste
emoji=true
experimental.strict_type_args=true
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
@@ -64,18 +63,17 @@ module.file_ext=.jsx
module.file_ext=.json
module.file_ext=.native.js
suppress_type=$FlowIgnore
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
unsafe.enable_getters_and_setters=true
[version]
^0.56.0
^0.67.0

View File

@@ -5,5 +5,6 @@ import renderer from 'react-test-renderer';
it('renders without crashing', () => {
const rendered = renderer.create(<App />).toJSON();
expect(rendered).toBeTruthy();
// Will be null because the playground uses state persistence which happens asyncronously
expect(rendered).toEqual(null);
});

View File

@@ -4,6 +4,6 @@ A playground for experimenting with react-navigation in a pure-JS React Native a
## Usage
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
Please see the [Contributors Guide](https://reactnavigation.org/docs/contributing.html#run-the-example-app) for instructions on running these example apps.
You can view this example application directly on your phone by visiting [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).

View File

@@ -7,21 +7,20 @@
"privacy": "public",
"orientation": "portrait",
"primaryColor": "#cccccc",
"icon": "./assets/icons/react-navigation.png",
"loading": {
"icon": "./assets/icons/react-navigation.png",
"hideExponentText": false
},
"sdkVersion": "24.0.0",
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"packagerOpts": {
"assetExts": [
"ttf",
"mp4"
]
"icon": "./assets/icons/icon.png",
"splash": {
"image": "./assets/icons/splash.png"
},
"sdkVersion": "28.0.0",
"assetBundlePatterns": [
"**/*"
],
"ios": {
"bundleIdentifier": "com.reactnavigation.example",
"supportsTablet": true
},
"android": {
"package": "com.reactnavigation.example"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

View File

@@ -1,5 +1,5 @@
// flow-typed signature: 5964a245d3129ecd50da1f74a2f86454
// flow-typed version: <<STUB>>/babel-jest_v^21.0.0/flow_v0.53.0
// flow-typed signature: ee7b4028012cfdcd83cc6541a39b2282
// flow-typed version: <<STUB>>/babel-jest_v^21.0.0/flow_v0.61.0
/**
* This is an autogenerated libdef stub for:

View File

@@ -1,5 +1,5 @@
// flow-typed signature: 4fb1f6897647ab1ad25d819aa06d2d6c
// flow-typed version: <<STUB>>/expo_v^22.0.0/flow_v0.53.0
// flow-typed signature: c1ecfe71fbb86c3602b7da3d7c141df1
// flow-typed version: <<STUB>>/expo_v^24.0.2/flow_v0.61.0
/**
* This is an autogenerated libdef stub for:
@@ -26,6 +26,18 @@ declare module 'expo/AppEntry' {
declare module.exports: any;
}
declare module 'expo/flow/metro-bundler' {
declare module.exports: any;
}
declare module 'expo/flow/react-native-gesture-handler' {
declare module.exports: any;
}
declare module 'expo/src/__mocks__/Constants-development' {
declare module.exports: any;
}
declare module 'expo/src/__tests__/Amplitude-test' {
declare module.exports: any;
}
@@ -50,6 +62,10 @@ declare module 'expo/src/__tests__/Facebook-test' {
declare module.exports: any;
}
declare module 'expo/src/__tests__/Font-test' {
declare module.exports: any;
}
declare module 'expo/src/__tests__/Location-test' {
declare module.exports: any;
}
@@ -70,6 +86,22 @@ declare module 'expo/src/__tests__/WebBrowser-test' {
declare module.exports: any;
}
declare module 'expo/src/admob/RNAdMobBanner' {
declare module.exports: any;
}
declare module 'expo/src/admob/RNAdMobInterstitial' {
declare module.exports: any;
}
declare module 'expo/src/admob/RNAdMobRewarded' {
declare module.exports: any;
}
declare module 'expo/src/admob/RNPublisherBanner' {
declare module.exports: any;
}
declare module 'expo/src/Amplitude' {
declare module.exports: any;
}
@@ -78,43 +110,39 @@ declare module 'expo/src/apisAreAvailable' {
declare module.exports: any;
}
declare module 'expo/src/AppLoading' {
declare module.exports: any;
}
declare module 'expo/src/AppLoadingNativeWrapper.android' {
declare module.exports: any;
}
declare module 'expo/src/AppLoadingNativeWrapper.ios' {
declare module.exports: any;
}
declare module 'expo/src/Asset' {
declare module.exports: any;
}
declare module 'expo/src/Audio' {
declare module.exports: any;
}
declare module 'expo/src/AuthSession' {
declare module.exports: any;
}
declare module 'expo/src/AV' {
declare module 'expo/src/av/Audio' {
declare module.exports: any;
}
declare module 'expo/src/BarCodeScanner' {
declare module 'expo/src/av/Audio/Recording' {
declare module.exports: any;
}
declare module 'expo/src/BlurView.android' {
declare module 'expo/src/av/Audio/Sound' {
declare module.exports: any;
}
declare module 'expo/src/BlurView.ios' {
declare module 'expo/src/av/AV' {
declare module.exports: any;
}
declare module 'expo/src/av/Video' {
declare module.exports: any;
}
declare module 'expo/src/BarCodeScanner.android' {
declare module.exports: any;
}
declare module 'expo/src/BarCodeScanner.ios' {
declare module.exports: any;
}
@@ -126,6 +154,10 @@ declare module 'expo/src/Camera' {
declare module.exports: any;
}
declare module 'expo/src/CameraBasedBarCodeScanner' {
declare module.exports: any;
}
declare module 'expo/src/Constants' {
declare module.exports: any;
}
@@ -142,6 +174,34 @@ declare module 'expo/src/DocumentPicker' {
declare module.exports: any;
}
declare module 'expo/src/effects/BlurView.android' {
declare module.exports: any;
}
declare module 'expo/src/effects/BlurView.ios' {
declare module.exports: any;
}
declare module 'expo/src/effects/LinearGradient.android' {
declare module.exports: any;
}
declare module 'expo/src/effects/LinearGradient.ios' {
declare module.exports: any;
}
declare module 'expo/src/environment/__tests__/validate-test' {
declare module.exports: any;
}
declare module 'expo/src/environment/logging' {
declare module.exports: any;
}
declare module 'expo/src/environment/validate' {
declare module.exports: any;
}
declare module 'expo/src/ErrorRecovery' {
declare module.exports: any;
}
@@ -150,31 +210,35 @@ declare module 'expo/src/Expo' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/AdSettings' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/BannerViewManager' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/index' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/InterstitialAdManager' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/NativeAdsManager' {
declare module.exports: any;
}
declare module 'expo/src/facebook-ads/withNativeAd' {
declare module.exports: any;
}
declare module 'expo/src/Facebook' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/AdSettings' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/BannerViewManager' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/index' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/InterstitialAdManager' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/NativeAdsManager' {
declare module.exports: any;
}
declare module 'expo/src/FacebookAds/withNativeAd' {
declare module 'expo/src/FaceDetector' {
declare module.exports: any;
}
@@ -202,6 +266,10 @@ declare module 'expo/src/Icon' {
declare module.exports: any;
}
declare module 'expo/src/ImageManipulator' {
declare module.exports: any;
}
declare module 'expo/src/ImagePicker' {
declare module.exports: any;
}
@@ -214,11 +282,23 @@ declare module 'expo/src/KeepAwake' {
declare module.exports: any;
}
declare module 'expo/src/LegacyAsyncStorage.android' {
declare module 'expo/src/launch/AppLoading' {
declare module.exports: any;
}
declare module 'expo/src/LegacyAsyncStorage.ios' {
declare module 'expo/src/launch/AppLoadingNativeWrapper.android' {
declare module.exports: any;
}
declare module 'expo/src/launch/AppLoadingNativeWrapper.ios' {
declare module.exports: any;
}
declare module 'expo/src/launch/registerRootComponent' {
declare module.exports: any;
}
declare module 'expo/src/launch/RootErrorBoundary' {
declare module.exports: any;
}
@@ -226,35 +306,59 @@ declare module 'expo/src/lib/Queue' {
declare module.exports: any;
}
declare module 'expo/src/LinearGradient.android' {
declare module.exports: any;
}
declare module 'expo/src/LinearGradient.ios' {
declare module.exports: any;
}
declare module 'expo/src/Location' {
declare module.exports: any;
}
declare module 'expo/src/Logs' {
declare module 'expo/src/logs/__tests__/Logs-test' {
declare module.exports: any;
}
declare module 'expo/src/Modal/Modal' {
declare module 'expo/src/logs/__tests__/LogSerialization-test' {
declare module.exports: any;
}
declare module 'expo/src/Modal/ModalHost' {
declare module 'expo/src/logs/__tests__/RemoteConsole-test' {
declare module.exports: any;
}
declare module 'expo/src/Modal/ModalImplementation' {
declare module 'expo/src/logs/__tests__/RemoteLogging-test' {
declare module.exports: any;
}
declare module 'expo/src/Modal/PureContainer' {
declare module 'expo/src/logs/__tests__/RemoteLogs-test' {
declare module.exports: any;
}
declare module 'expo/src/logs/Logs' {
declare module.exports: any;
}
declare module 'expo/src/logs/LogSerialization' {
declare module.exports: any;
}
declare module 'expo/src/logs/RemoteConsole' {
declare module.exports: any;
}
declare module 'expo/src/logs/RemoteLogging' {
declare module.exports: any;
}
declare module 'expo/src/modal/Modal' {
declare module.exports: any;
}
declare module 'expo/src/modal/ModalHost' {
declare module.exports: any;
}
declare module 'expo/src/modal/ModalImplementation' {
declare module.exports: any;
}
declare module 'expo/src/modal/PureContainer' {
declare module.exports: any;
}
@@ -262,6 +366,10 @@ declare module 'expo/src/Notifications' {
declare module.exports: any;
}
declare module 'expo/src/OldBarCodeScanner' {
declare module.exports: any;
}
declare module 'expo/src/Payments' {
declare module.exports: any;
}
@@ -274,30 +382,6 @@ declare module 'expo/src/Permissions' {
declare module.exports: any;
}
declare module 'expo/src/registerRootComponent' {
declare module.exports: any;
}
declare module 'expo/src/RNAdMobBanner' {
declare module.exports: any;
}
declare module 'expo/src/RNAdMobInterstitial' {
declare module.exports: any;
}
declare module 'expo/src/RNAdMobRewarded' {
declare module.exports: any;
}
declare module 'expo/src/RNPublisherBanner' {
declare module.exports: any;
}
declare module 'expo/src/RootErrorBoundary' {
declare module.exports: any;
}
declare module 'expo/src/ScreenOrientation' {
declare module.exports: any;
}
@@ -374,11 +458,11 @@ declare module 'expo/src/takeSnapshotAsync' {
declare module.exports: any;
}
declare module 'expo/src/Util' {
declare module 'expo/src/timer/polyfillNextTick' {
declare module.exports: any;
}
declare module 'expo/src/Video' {
declare module 'expo/src/Util' {
declare module.exports: any;
}
@@ -398,6 +482,15 @@ declare module 'expo/tools/LogReporter' {
declare module 'expo/AppEntry.js' {
declare module.exports: $Exports<'expo/AppEntry'>;
}
declare module 'expo/flow/metro-bundler.js' {
declare module.exports: $Exports<'expo/flow/metro-bundler'>;
}
declare module 'expo/flow/react-native-gesture-handler.js' {
declare module.exports: $Exports<'expo/flow/react-native-gesture-handler'>;
}
declare module 'expo/src/__mocks__/Constants-development.js' {
declare module.exports: $Exports<'expo/src/__mocks__/Constants-development'>;
}
declare module 'expo/src/__tests__/Amplitude-test.js' {
declare module.exports: $Exports<'expo/src/__tests__/Amplitude-test'>;
}
@@ -416,6 +509,9 @@ declare module 'expo/src/__tests__/Expo-test.js' {
declare module 'expo/src/__tests__/Facebook-test.js' {
declare module.exports: $Exports<'expo/src/__tests__/Facebook-test'>;
}
declare module 'expo/src/__tests__/Font-test.js' {
declare module.exports: $Exports<'expo/src/__tests__/Font-test'>;
}
declare module 'expo/src/__tests__/Location-test.js' {
declare module.exports: $Exports<'expo/src/__tests__/Location-test'>;
}
@@ -431,41 +527,50 @@ declare module 'expo/src/__tests__/Segment-test.js' {
declare module 'expo/src/__tests__/WebBrowser-test.js' {
declare module.exports: $Exports<'expo/src/__tests__/WebBrowser-test'>;
}
declare module 'expo/src/admob/RNAdMobBanner.js' {
declare module.exports: $Exports<'expo/src/admob/RNAdMobBanner'>;
}
declare module 'expo/src/admob/RNAdMobInterstitial.js' {
declare module.exports: $Exports<'expo/src/admob/RNAdMobInterstitial'>;
}
declare module 'expo/src/admob/RNAdMobRewarded.js' {
declare module.exports: $Exports<'expo/src/admob/RNAdMobRewarded'>;
}
declare module 'expo/src/admob/RNPublisherBanner.js' {
declare module.exports: $Exports<'expo/src/admob/RNPublisherBanner'>;
}
declare module 'expo/src/Amplitude.js' {
declare module.exports: $Exports<'expo/src/Amplitude'>;
}
declare module 'expo/src/apisAreAvailable.js' {
declare module.exports: $Exports<'expo/src/apisAreAvailable'>;
}
declare module 'expo/src/AppLoading.js' {
declare module.exports: $Exports<'expo/src/AppLoading'>;
}
declare module 'expo/src/AppLoadingNativeWrapper.android.js' {
declare module.exports: $Exports<'expo/src/AppLoadingNativeWrapper.android'>;
}
declare module 'expo/src/AppLoadingNativeWrapper.ios.js' {
declare module.exports: $Exports<'expo/src/AppLoadingNativeWrapper.ios'>;
}
declare module 'expo/src/Asset.js' {
declare module.exports: $Exports<'expo/src/Asset'>;
}
declare module 'expo/src/Audio.js' {
declare module.exports: $Exports<'expo/src/Audio'>;
}
declare module 'expo/src/AuthSession.js' {
declare module.exports: $Exports<'expo/src/AuthSession'>;
}
declare module 'expo/src/AV.js' {
declare module.exports: $Exports<'expo/src/AV'>;
declare module 'expo/src/av/Audio.js' {
declare module.exports: $Exports<'expo/src/av/Audio'>;
}
declare module 'expo/src/BarCodeScanner.js' {
declare module.exports: $Exports<'expo/src/BarCodeScanner'>;
declare module 'expo/src/av/Audio/Recording.js' {
declare module.exports: $Exports<'expo/src/av/Audio/Recording'>;
}
declare module 'expo/src/BlurView.android.js' {
declare module.exports: $Exports<'expo/src/BlurView.android'>;
declare module 'expo/src/av/Audio/Sound.js' {
declare module.exports: $Exports<'expo/src/av/Audio/Sound'>;
}
declare module 'expo/src/BlurView.ios.js' {
declare module.exports: $Exports<'expo/src/BlurView.ios'>;
declare module 'expo/src/av/AV.js' {
declare module.exports: $Exports<'expo/src/av/AV'>;
}
declare module 'expo/src/av/Video.js' {
declare module.exports: $Exports<'expo/src/av/Video'>;
}
declare module 'expo/src/BarCodeScanner.android.js' {
declare module.exports: $Exports<'expo/src/BarCodeScanner.android'>;
}
declare module 'expo/src/BarCodeScanner.ios.js' {
declare module.exports: $Exports<'expo/src/BarCodeScanner.ios'>;
}
declare module 'expo/src/Brightness.js' {
declare module.exports: $Exports<'expo/src/Brightness'>;
@@ -473,6 +578,9 @@ declare module 'expo/src/Brightness.js' {
declare module 'expo/src/Camera.js' {
declare module.exports: $Exports<'expo/src/Camera'>;
}
declare module 'expo/src/CameraBasedBarCodeScanner.js' {
declare module.exports: $Exports<'expo/src/CameraBasedBarCodeScanner'>;
}
declare module 'expo/src/Constants.js' {
declare module.exports: $Exports<'expo/src/Constants'>;
}
@@ -485,32 +593,56 @@ declare module 'expo/src/DangerZone.js' {
declare module 'expo/src/DocumentPicker.js' {
declare module.exports: $Exports<'expo/src/DocumentPicker'>;
}
declare module 'expo/src/effects/BlurView.android.js' {
declare module.exports: $Exports<'expo/src/effects/BlurView.android'>;
}
declare module 'expo/src/effects/BlurView.ios.js' {
declare module.exports: $Exports<'expo/src/effects/BlurView.ios'>;
}
declare module 'expo/src/effects/LinearGradient.android.js' {
declare module.exports: $Exports<'expo/src/effects/LinearGradient.android'>;
}
declare module 'expo/src/effects/LinearGradient.ios.js' {
declare module.exports: $Exports<'expo/src/effects/LinearGradient.ios'>;
}
declare module 'expo/src/environment/__tests__/validate-test.js' {
declare module.exports: $Exports<'expo/src/environment/__tests__/validate-test'>;
}
declare module 'expo/src/environment/logging.js' {
declare module.exports: $Exports<'expo/src/environment/logging'>;
}
declare module 'expo/src/environment/validate.js' {
declare module.exports: $Exports<'expo/src/environment/validate'>;
}
declare module 'expo/src/ErrorRecovery.js' {
declare module.exports: $Exports<'expo/src/ErrorRecovery'>;
}
declare module 'expo/src/Expo.js' {
declare module.exports: $Exports<'expo/src/Expo'>;
}
declare module 'expo/src/facebook-ads/AdSettings.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/AdSettings'>;
}
declare module 'expo/src/facebook-ads/BannerViewManager.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/BannerViewManager'>;
}
declare module 'expo/src/facebook-ads/index.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/index'>;
}
declare module 'expo/src/facebook-ads/InterstitialAdManager.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/InterstitialAdManager'>;
}
declare module 'expo/src/facebook-ads/NativeAdsManager.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/NativeAdsManager'>;
}
declare module 'expo/src/facebook-ads/withNativeAd.js' {
declare module.exports: $Exports<'expo/src/facebook-ads/withNativeAd'>;
}
declare module 'expo/src/Facebook.js' {
declare module.exports: $Exports<'expo/src/Facebook'>;
}
declare module 'expo/src/FacebookAds/AdSettings.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/AdSettings'>;
}
declare module 'expo/src/FacebookAds/BannerViewManager.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/BannerViewManager'>;
}
declare module 'expo/src/FacebookAds/index.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/index'>;
}
declare module 'expo/src/FacebookAds/InterstitialAdManager.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/InterstitialAdManager'>;
}
declare module 'expo/src/FacebookAds/NativeAdsManager.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/NativeAdsManager'>;
}
declare module 'expo/src/FacebookAds/withNativeAd.js' {
declare module.exports: $Exports<'expo/src/FacebookAds/withNativeAd'>;
declare module 'expo/src/FaceDetector.js' {
declare module.exports: $Exports<'expo/src/FaceDetector'>;
}
declare module 'expo/src/FileSystem.js' {
declare module.exports: $Exports<'expo/src/FileSystem'>;
@@ -530,6 +662,9 @@ declare module 'expo/src/Google.js' {
declare module 'expo/src/Icon.js' {
declare module.exports: $Exports<'expo/src/Icon'>;
}
declare module 'expo/src/ImageManipulator.js' {
declare module.exports: $Exports<'expo/src/ImageManipulator'>;
}
declare module 'expo/src/ImagePicker.js' {
declare module.exports: $Exports<'expo/src/ImagePicker'>;
}
@@ -539,42 +674,72 @@ declare module 'expo/src/IntentLauncherAndroid.js' {
declare module 'expo/src/KeepAwake.js' {
declare module.exports: $Exports<'expo/src/KeepAwake'>;
}
declare module 'expo/src/LegacyAsyncStorage.android.js' {
declare module.exports: $Exports<'expo/src/LegacyAsyncStorage.android'>;
declare module 'expo/src/launch/AppLoading.js' {
declare module.exports: $Exports<'expo/src/launch/AppLoading'>;
}
declare module 'expo/src/LegacyAsyncStorage.ios.js' {
declare module.exports: $Exports<'expo/src/LegacyAsyncStorage.ios'>;
declare module 'expo/src/launch/AppLoadingNativeWrapper.android.js' {
declare module.exports: $Exports<'expo/src/launch/AppLoadingNativeWrapper.android'>;
}
declare module 'expo/src/launch/AppLoadingNativeWrapper.ios.js' {
declare module.exports: $Exports<'expo/src/launch/AppLoadingNativeWrapper.ios'>;
}
declare module 'expo/src/launch/registerRootComponent.js' {
declare module.exports: $Exports<'expo/src/launch/registerRootComponent'>;
}
declare module 'expo/src/launch/RootErrorBoundary.js' {
declare module.exports: $Exports<'expo/src/launch/RootErrorBoundary'>;
}
declare module 'expo/src/lib/Queue.js' {
declare module.exports: $Exports<'expo/src/lib/Queue'>;
}
declare module 'expo/src/LinearGradient.android.js' {
declare module.exports: $Exports<'expo/src/LinearGradient.android'>;
}
declare module 'expo/src/LinearGradient.ios.js' {
declare module.exports: $Exports<'expo/src/LinearGradient.ios'>;
}
declare module 'expo/src/Location.js' {
declare module.exports: $Exports<'expo/src/Location'>;
}
declare module 'expo/src/Logs.js' {
declare module.exports: $Exports<'expo/src/Logs'>;
declare module 'expo/src/logs/__tests__/Logs-test.js' {
declare module.exports: $Exports<'expo/src/logs/__tests__/Logs-test'>;
}
declare module 'expo/src/Modal/Modal.js' {
declare module.exports: $Exports<'expo/src/Modal/Modal'>;
declare module 'expo/src/logs/__tests__/LogSerialization-test.js' {
declare module.exports: $Exports<'expo/src/logs/__tests__/LogSerialization-test'>;
}
declare module 'expo/src/Modal/ModalHost.js' {
declare module.exports: $Exports<'expo/src/Modal/ModalHost'>;
declare module 'expo/src/logs/__tests__/RemoteConsole-test.js' {
declare module.exports: $Exports<'expo/src/logs/__tests__/RemoteConsole-test'>;
}
declare module 'expo/src/Modal/ModalImplementation.js' {
declare module.exports: $Exports<'expo/src/Modal/ModalImplementation'>;
declare module 'expo/src/logs/__tests__/RemoteLogging-test.js' {
declare module.exports: $Exports<'expo/src/logs/__tests__/RemoteLogging-test'>;
}
declare module 'expo/src/Modal/PureContainer.js' {
declare module.exports: $Exports<'expo/src/Modal/PureContainer'>;
declare module 'expo/src/logs/__tests__/RemoteLogs-test.js' {
declare module.exports: $Exports<'expo/src/logs/__tests__/RemoteLogs-test'>;
}
declare module 'expo/src/logs/Logs.js' {
declare module.exports: $Exports<'expo/src/logs/Logs'>;
}
declare module 'expo/src/logs/LogSerialization.js' {
declare module.exports: $Exports<'expo/src/logs/LogSerialization'>;
}
declare module 'expo/src/logs/RemoteConsole.js' {
declare module.exports: $Exports<'expo/src/logs/RemoteConsole'>;
}
declare module 'expo/src/logs/RemoteLogging.js' {
declare module.exports: $Exports<'expo/src/logs/RemoteLogging'>;
}
declare module 'expo/src/modal/Modal.js' {
declare module.exports: $Exports<'expo/src/modal/Modal'>;
}
declare module 'expo/src/modal/ModalHost.js' {
declare module.exports: $Exports<'expo/src/modal/ModalHost'>;
}
declare module 'expo/src/modal/ModalImplementation.js' {
declare module.exports: $Exports<'expo/src/modal/ModalImplementation'>;
}
declare module 'expo/src/modal/PureContainer.js' {
declare module.exports: $Exports<'expo/src/modal/PureContainer'>;
}
declare module 'expo/src/Notifications.js' {
declare module.exports: $Exports<'expo/src/Notifications'>;
}
declare module 'expo/src/OldBarCodeScanner.js' {
declare module.exports: $Exports<'expo/src/OldBarCodeScanner'>;
}
declare module 'expo/src/Payments.js' {
declare module.exports: $Exports<'expo/src/Payments'>;
}
@@ -584,24 +749,6 @@ declare module 'expo/src/Pedometer.js' {
declare module 'expo/src/Permissions.js' {
declare module.exports: $Exports<'expo/src/Permissions'>;
}
declare module 'expo/src/registerRootComponent.js' {
declare module.exports: $Exports<'expo/src/registerRootComponent'>;
}
declare module 'expo/src/RNAdMobBanner.js' {
declare module.exports: $Exports<'expo/src/RNAdMobBanner'>;
}
declare module 'expo/src/RNAdMobInterstitial.js' {
declare module.exports: $Exports<'expo/src/RNAdMobInterstitial'>;
}
declare module 'expo/src/RNAdMobRewarded.js' {
declare module.exports: $Exports<'expo/src/RNAdMobRewarded'>;
}
declare module 'expo/src/RNPublisherBanner.js' {
declare module.exports: $Exports<'expo/src/RNPublisherBanner'>;
}
declare module 'expo/src/RootErrorBoundary.js' {
declare module.exports: $Exports<'expo/src/RootErrorBoundary'>;
}
declare module 'expo/src/ScreenOrientation.js' {
declare module.exports: $Exports<'expo/src/ScreenOrientation'>;
}
@@ -659,12 +806,12 @@ declare module 'expo/src/Svg.js' {
declare module 'expo/src/takeSnapshotAsync.js' {
declare module.exports: $Exports<'expo/src/takeSnapshotAsync'>;
}
declare module 'expo/src/timer/polyfillNextTick.js' {
declare module.exports: $Exports<'expo/src/timer/polyfillNextTick'>;
}
declare module 'expo/src/Util.js' {
declare module.exports: $Exports<'expo/src/Util'>;
}
declare module 'expo/src/Video.js' {
declare module.exports: $Exports<'expo/src/Video'>;
}
declare module 'expo/src/WebBrowser.js' {
declare module.exports: $Exports<'expo/src/WebBrowser'>;
}

View File

@@ -1,5 +1,5 @@
// flow-typed signature: 72ab5b9c7dcb88b82de627702a0db27a
// flow-typed version: <<STUB>>/jest-expo_v^22.0.0/flow_v0.53.0
// flow-typed signature: b1e3826a494aecf4ff482336321b54bd
// flow-typed version: <<STUB>>/jest-expo_v^24.0.0/flow_v0.61.0
/**
* This is an autogenerated libdef stub for:

View File

@@ -1,528 +0,0 @@
// flow-typed signature: a0369c11661f437ec4ccdd805579ddcf
// flow-typed version: c4b9fea7c9/jest_v20.x.x/flow_>=v0.33.x
type JestMockFn = {
(...args: Array<any>): any,
/**
* An object for introspecting mock calls
*/
mock: {
/**
* An array that represents all calls that have been made into this mock
* function. Each call is represented by an array of arguments that were
* passed during the call.
*/
calls: Array<Array<any>>,
/**
* An array that contains all the object instances that have been
* instantiated from this mock function.
*/
instances: mixed
},
/**
* Resets all information stored in the mockFn.mock.calls and
* mockFn.mock.instances arrays. Often this is useful when you want to clean
* up a mock's usage data between two assertions.
*/
mockClear(): Function,
/**
* Resets all information stored in the mock. This is useful when you want to
* completely restore a mock back to its initial state.
*/
mockReset(): Function,
/**
* Removes the mock and restores the initial implementation. This is useful
* when you want to mock functions in certain test cases and restore the
* original implementation in others. Beware that mockFn.mockRestore only
* works when mock was created with jest.spyOn. Thus you have to take care of
* restoration yourself when manually assigning jest.fn().
*/
mockRestore(): Function,
/**
* Accepts a function that should be used as the implementation of the mock.
* The mock itself will still record all calls that go into and instances
* that come from itself -- the only difference is that the implementation
* will also be executed when the mock is called.
*/
mockImplementation(fn: Function): JestMockFn,
/**
* Accepts a function that will be used as an implementation of the mock for
* one call to the mocked function. Can be chained so that multiple function
* calls produce different results.
*/
mockImplementationOnce(fn: Function): JestMockFn,
/**
* Just a simple sugar function for returning `this`
*/
mockReturnThis(): void,
/**
* Deprecated: use jest.fn(() => value) instead
*/
mockReturnValue(value: any): JestMockFn,
/**
* Sugar for only returning a value once inside your mock
*/
mockReturnValueOnce(value: any): JestMockFn
};
type JestAsymmetricEqualityType = {
/**
* A custom Jasmine equality tester
*/
asymmetricMatch(value: mixed): boolean
};
type JestCallsType = {
allArgs(): mixed,
all(): mixed,
any(): boolean,
count(): number,
first(): mixed,
mostRecent(): mixed,
reset(): void
};
type JestClockType = {
install(): void,
mockDate(date: Date): void,
tick(milliseconds?: number): void,
uninstall(): void
};
type JestMatcherResult = {
message?: string | (() => string),
pass: boolean
};
type JestMatcher = (actual: any, expected: any) => JestMatcherResult;
type JestPromiseType = {
/**
* Use rejects to unwrap the reason of a rejected promise so any other
* matcher can be chained. If the promise is fulfilled the assertion fails.
*/
rejects: JestExpectType,
/**
* Use resolves to unwrap the value of a fulfilled promise so any other
* matcher can be chained. If the promise is rejected the assertion fails.
*/
resolves: JestExpectType
};
/**
* Plugin: jest-enzyme
*/
type EnzymeMatchersType = {
toBeChecked(): void,
toBeDisabled(): void,
toBeEmpty(): void,
toBePresent(): void,
toContainReact(element: React$Element<any>): void,
toHaveClassName(className: string): void,
toHaveHTML(html: string): void,
toHaveProp(propKey: string, propValue?: any): void,
toHaveRef(refName: string): void,
toHaveState(stateKey: string, stateValue?: any): void,
toHaveStyle(styleKey: string, styleValue?: any): void,
toHaveTagName(tagName: string): void,
toHaveText(text: string): void,
toIncludeText(text: string): void,
toHaveValue(value: any): void,
toMatchElement(element: React$Element<any>): void,
toMatchSelector(selector: string): void,
};
type JestExpectType = {
not: JestExpectType & EnzymeMatchersType,
/**
* If you have a mock function, you can use .lastCalledWith to test what
* arguments it was last called with.
*/
lastCalledWith(...args: Array<any>): void,
/**
* toBe just checks that a value is what you expect. It uses === to check
* strict equality.
*/
toBe(value: any): void,
/**
* Use .toHaveBeenCalled to ensure that a mock function got called.
*/
toBeCalled(): void,
/**
* Use .toBeCalledWith to ensure that a mock function was called with
* specific arguments.
*/
toBeCalledWith(...args: Array<any>): void,
/**
* Using exact equality with floating point numbers is a bad idea. Rounding
* means that intuitive things fail.
*/
toBeCloseTo(num: number, delta: any): void,
/**
* Use .toBeDefined to check that a variable is not undefined.
*/
toBeDefined(): void,
/**
* Use .toBeFalsy when you don't care what a value is, you just want to
* ensure a value is false in a boolean context.
*/
toBeFalsy(): void,
/**
* To compare floating point numbers, you can use toBeGreaterThan.
*/
toBeGreaterThan(number: number): void,
/**
* To compare floating point numbers, you can use toBeGreaterThanOrEqual.
*/
toBeGreaterThanOrEqual(number: number): void,
/**
* To compare floating point numbers, you can use toBeLessThan.
*/
toBeLessThan(number: number): void,
/**
* To compare floating point numbers, you can use toBeLessThanOrEqual.
*/
toBeLessThanOrEqual(number: number): void,
/**
* Use .toBeInstanceOf(Class) to check that an object is an instance of a
* class.
*/
toBeInstanceOf(cls: Class<*>): void,
/**
* .toBeNull() is the same as .toBe(null) but the error messages are a bit
* nicer.
*/
toBeNull(): void,
/**
* Use .toBeTruthy when you don't care what a value is, you just want to
* ensure a value is true in a boolean context.
*/
toBeTruthy(): void,
/**
* Use .toBeUndefined to check that a variable is undefined.
*/
toBeUndefined(): void,
/**
* Use .toContain when you want to check that an item is in a list. For
* testing the items in the list, this uses ===, a strict equality check.
*/
toContain(item: any): void,
/**
* Use .toContainEqual when you want to check that an item is in a list. For
* testing the items in the list, this matcher recursively checks the
* equality of all fields, rather than checking for object identity.
*/
toContainEqual(item: any): void,
/**
* Use .toEqual when you want to check that two objects have the same value.
* This matcher recursively checks the equality of all fields, rather than
* checking for object identity.
*/
toEqual(value: any): void,
/**
* Use .toHaveBeenCalled to ensure that a mock function got called.
*/
toHaveBeenCalled(): void,
/**
* Use .toHaveBeenCalledTimes to ensure that a mock function got called exact
* number of times.
*/
toHaveBeenCalledTimes(number: number): void,
/**
* Use .toHaveBeenCalledWith to ensure that a mock function was called with
* specific arguments.
*/
toHaveBeenCalledWith(...args: Array<any>): void,
/**
* Use .toHaveBeenLastCalledWith to ensure that a mock function was last called
* with specific arguments.
*/
toHaveBeenLastCalledWith(...args: Array<any>): void,
/**
* Check that an object has a .length property and it is set to a certain
* numeric value.
*/
toHaveLength(number: number): void,
/**
*
*/
toHaveProperty(propPath: string, value?: any): void,
/**
* Use .toMatch to check that a string matches a regular expression or string.
*/
toMatch(regexpOrString: RegExp | string): void,
/**
* Use .toMatchObject to check that a javascript object matches a subset of the properties of an object.
*/
toMatchObject(object: Object): void,
/**
* This ensures that a React component matches the most recent snapshot.
*/
toMatchSnapshot(name?: string): void,
/**
* Use .toThrow to test that a function throws when it is called.
* If you want to test that a specific error gets thrown, you can provide an
* argument to toThrow. The argument can be a string for the error message,
* a class for the error, or a regex that should match the error.
*
* Alias: .toThrowError
*/
toThrow(message?: string | Error | RegExp): void,
toThrowError(message?: string | Error | RegExp): void,
/**
* Use .toThrowErrorMatchingSnapshot to test that a function throws a error
* matching the most recent snapshot when it is called.
*/
toThrowErrorMatchingSnapshot(): void
};
type JestObjectType = {
/**
* Disables automatic mocking in the module loader.
*
* After this method is called, all `require()`s will return the real
* versions of each module (rather than a mocked version).
*/
disableAutomock(): JestObjectType,
/**
* An un-hoisted version of disableAutomock
*/
autoMockOff(): JestObjectType,
/**
* Enables automatic mocking in the module loader.
*/
enableAutomock(): JestObjectType,
/**
* An un-hoisted version of enableAutomock
*/
autoMockOn(): JestObjectType,
/**
* Clears the mock.calls and mock.instances properties of all mocks.
* Equivalent to calling .mockClear() on every mocked function.
*/
clearAllMocks(): JestObjectType,
/**
* Resets the state of all mocks. Equivalent to calling .mockReset() on every
* mocked function.
*/
resetAllMocks(): JestObjectType,
/**
* Removes any pending timers from the timer system.
*/
clearAllTimers(): void,
/**
* The same as `mock` but not moved to the top of the expectation by
* babel-jest.
*/
doMock(moduleName: string, moduleFactory?: any): JestObjectType,
/**
* The same as `unmock` but not moved to the top of the expectation by
* babel-jest.
*/
dontMock(moduleName: string): JestObjectType,
/**
* Returns a new, unused mock function. Optionally takes a mock
* implementation.
*/
fn(implementation?: Function): JestMockFn,
/**
* Determines if the given function is a mocked function.
*/
isMockFunction(fn: Function): boolean,
/**
* Given the name of a module, use the automatic mocking system to generate a
* mocked version of the module for you.
*/
genMockFromModule(moduleName: string): any,
/**
* Mocks a module with an auto-mocked version when it is being required.
*
* The second argument can be used to specify an explicit module factory that
* is being run instead of using Jest's automocking feature.
*
* The third argument can be used to create virtual mocks -- mocks of modules
* that don't exist anywhere in the system.
*/
mock(
moduleName: string,
moduleFactory?: any,
options?: Object
): JestObjectType,
/**
* Resets the module registry - the cache of all required modules. This is
* useful to isolate modules where local state might conflict between tests.
*/
resetModules(): JestObjectType,
/**
* Exhausts the micro-task queue (usually interfaced in node via
* process.nextTick).
*/
runAllTicks(): void,
/**
* Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(),
* setInterval(), and setImmediate()).
*/
runAllTimers(): void,
/**
* Exhausts all tasks queued by setImmediate().
*/
runAllImmediates(): void,
/**
* Executes only the macro task queue (i.e. all tasks queued by setTimeout()
* or setInterval() and setImmediate()).
*/
runTimersToTime(msToRun: number): void,
/**
* Executes only the macro-tasks that are currently pending (i.e., only the
* tasks that have been queued by setTimeout() or setInterval() up to this
* point)
*/
runOnlyPendingTimers(): void,
/**
* Explicitly supplies the mock object that the module system should return
* for the specified module. Note: It is recommended to use jest.mock()
* instead.
*/
setMock(moduleName: string, moduleExports: any): JestObjectType,
/**
* Indicates that the module system should never return a mocked version of
* the specified module from require() (e.g. that it should always return the
* real module).
*/
unmock(moduleName: string): JestObjectType,
/**
* Instructs Jest to use fake versions of the standard timer functions
* (setTimeout, setInterval, clearTimeout, clearInterval, nextTick,
* setImmediate and clearImmediate).
*/
useFakeTimers(): JestObjectType,
/**
* Instructs Jest to use the real versions of the standard timer functions.
*/
useRealTimers(): JestObjectType,
/**
* Creates a mock function similar to jest.fn but also tracks calls to
* object[methodName].
*/
spyOn(object: Object, methodName: string): JestMockFn
};
type JestSpyType = {
calls: JestCallsType
};
/** Runs this function after every test inside this context */
declare function afterEach(fn: Function): void;
/** Runs this function before every test inside this context */
declare function beforeEach(fn: Function): void;
/** Runs this function after all tests have finished inside this context */
declare function afterAll(fn: Function): void;
/** Runs this function before any tests have started inside this context */
declare function beforeAll(fn: Function): void;
/** A context for grouping tests together */
declare var describe: {
/**
* Creates a block that groups together several related tests in one "test suite"
*/
(name: string, fn: Function): void,
/**
* Only run this describe block
*/
only(name: string, fn: Function): void,
/**
* Skip running this describe block
*/
skip(name: string, fn: Function): void,
};
/** An individual test unit */
declare var it: {
/**
* An individual test unit
*
* @param {string} Name of Test
* @param {Function} Test
*/
(name: string, fn?: Function): ?Promise<void>,
/**
* Only run this test
*
* @param {string} Name of Test
* @param {Function} Test
*/
only(name: string, fn?: Function): ?Promise<void>,
/**
* Skip running this test
*
* @param {string} Name of Test
* @param {Function} Test
*/
skip(name: string, fn?: Function): ?Promise<void>,
/**
* Run the test concurrently
*
* @param {string} Name of Test
* @param {Function} Test
*/
concurrent(name: string, fn?: Function): ?Promise<void>
};
declare function fit(name: string, fn: Function): ?Promise<void>;
/** An individual test unit */
declare var test: typeof it;
/** A disabled group of tests */
declare var xdescribe: typeof describe;
/** A focused group of tests */
declare var fdescribe: typeof describe;
/** A disabled individual test */
declare var xit: typeof it;
/** A disabled individual test */
declare var xtest: typeof it;
/** The expect function is used every time you want to test a value */
declare var expect: {
/** The object that you want to make assertions against */
(value: any): JestExpectType & JestPromiseType & EnzymeMatchersType,
/** Add additional Jasmine matchers to Jest's roster */
extend(matchers: { [name: string]: JestMatcher }): void,
/** Add a module that formats application-specific data structures. */
addSnapshotSerializer(serializer: (input: Object) => string): void,
assertions(expectedAssertions: number): void,
hasAssertions(): void,
any(value: mixed): JestAsymmetricEqualityType,
anything(): void,
arrayContaining(value: Array<mixed>): void,
objectContaining(value: Object): void,
/** Matches any received string that contains the exact expected string. */
stringContaining(value: string): void,
stringMatching(value: string | RegExp): void
};
// TODO handle return type
// http://jasmine.github.io/2.4/introduction.html#section-Spies
declare function spyOn(value: mixed, method: string): Object;
/** Holds all functions related to manipulating test runner */
declare var jest: JestObjectType;
/**
* The global Jamine object, this is generally not exposed as the public API,
* using features inside here could break in later versions of Jest.
*/
declare var jasmine: {
DEFAULT_TIMEOUT_INTERVAL: number,
any(value: mixed): JestAsymmetricEqualityType,
anything(): void,
arrayContaining(value: Array<mixed>): void,
clock(): JestClockType,
createSpy(name: string): JestSpyType,
createSpyObj(
baseName: string,
methodNames: Array<string>
): { [methodName: string]: JestSpyType },
objectContaining(value: Object): void,
stringMatching(value: string): void
};

View File

@@ -1,5 +1,5 @@
// flow-typed signature: 5960ed076fe29ecf92f57584d68acf98
// flow-typed version: b2a49dc910/jest_v20.x.x/flow_>=v0.39.x
// flow-typed signature: 107cf7068b8835594e97f938e8848244
// flow-typed version: 8b4dd96654/jest_v21.x.x/flow_>=v0.39.x
type JestMockFn<TArguments: $ReadOnlyArray<*>, TReturn> = {
(...args: TArguments): TReturn,
@@ -45,7 +45,7 @@ type JestMockFn<TArguments: $ReadOnlyArray<*>, TReturn> = {
* will also be executed when the mock is called.
*/
mockImplementation(
fn: (...args: TArguments) => TReturn,
fn: (...args: TArguments) => TReturn
): JestMockFn<TArguments, TReturn>,
/**
* Accepts a function that will be used as an implementation of the mock for
@@ -53,7 +53,7 @@ type JestMockFn<TArguments: $ReadOnlyArray<*>, TReturn> = {
* calls produce different results.
*/
mockImplementationOnce(
fn: (...args: TArguments) => TReturn,
fn: (...args: TArguments) => TReturn
): JestMockFn<TArguments, TReturn>,
/**
* Just a simple sugar function for returning `this`
@@ -133,7 +133,7 @@ type EnzymeMatchersType = {
toIncludeText(text: string): void,
toHaveValue(value: any): void,
toMatchElement(element: React$Element<any>): void,
toMatchSelector(selector: string): void,
toMatchSelector(selector: string): void
};
type JestExpectType = {
@@ -258,7 +258,7 @@ type JestExpectType = {
/**
* Use .toMatchObject to check that a javascript object matches a subset of the properties of an object.
*/
toMatchObject(object: Object): void,
toMatchObject(object: Object | Array<Object>): void,
/**
* This ensures that a React component matches the most recent snapshot.
*/
@@ -271,8 +271,8 @@ type JestExpectType = {
*
* Alias: .toThrowError
*/
toThrow(message?: string | Error | RegExp): void,
toThrowError(message?: string | Error | RegExp): void,
toThrow(message?: string | Error | Class<Error> | RegExp): void,
toThrowError(message?: string | Error | Class<Error> | RegExp): void,
/**
* Use .toThrowErrorMatchingSnapshot to test that a function throws a error
* matching the most recent snapshot when it is called.
@@ -329,7 +329,7 @@ type JestObjectType = {
* implementation.
*/
fn<TArguments: $ReadOnlyArray<*>, TReturn>(
implementation?: (...args: TArguments) => TReturn,
implementation?: (...args: TArguments) => TReturn
): JestMockFn<TArguments, TReturn>,
/**
* Determines if the given function is a mocked function.
@@ -354,6 +354,16 @@ type JestObjectType = {
moduleFactory?: any,
options?: Object
): JestObjectType,
/**
* Returns the actual module instead of a mock, bypassing all checks on
* whether the module should receive a mock implementation or not.
*/
requireActual(moduleName: string): any,
/**
* Returns a mock module instead of the actual module, bypassing all checks
* on whether the module should be required normally or not.
*/
requireMock(moduleName: string): any,
/**
* Resets the module registry - the cache of all required modules. This is
* useful to isolate modules where local state might conflict between tests.
@@ -410,7 +420,12 @@ type JestObjectType = {
* Creates a mock function similar to jest.fn but also tracks calls to
* object[methodName].
*/
spyOn(object: Object, methodName: string): JestMockFn<any, any>
spyOn(object: Object, methodName: string): JestMockFn<any, any>,
/**
* Set the default timeout interval for tests and before/after hooks in milliseconds.
* Note: The default timeout interval is 5 seconds if this method is not called.
*/
setTimeout(timeout: number): JestObjectType
};
type JestSpyType = {
@@ -418,13 +433,25 @@ type JestSpyType = {
};
/** Runs this function after every test inside this context */
declare function afterEach(fn: (done: () => void) => ?Promise<mixed>, timeout?: number): void;
declare function afterEach(
fn: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void;
/** Runs this function before every test inside this context */
declare function beforeEach(fn: (done: () => void) => ?Promise<mixed>, timeout?: number): void;
declare function beforeEach(
fn: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void;
/** Runs this function after all tests have finished inside this context */
declare function afterAll(fn: (done: () => void) => ?Promise<mixed>, timeout?: number): void;
declare function afterAll(
fn: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void;
/** Runs this function before any tests have started inside this context */
declare function beforeAll(fn: (done: () => void) => ?Promise<mixed>, timeout?: number): void;
declare function beforeAll(
fn: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void;
/** A context for grouping tests together */
declare var describe: {
@@ -441,10 +468,9 @@ declare var describe: {
/**
* Skip running this describe block
*/
skip(name: string, fn: () => void): void,
skip(name: string, fn: () => void): void
};
/** An individual test unit */
declare var it: {
/**
@@ -454,7 +480,11 @@ declare var it: {
* @param {Function} Test
* @param {number} Timeout for the test, in milliseconds.
*/
(name: string, fn?: (done: () => void) => ?Promise<mixed>, timeout?: number): void,
(
name: string,
fn?: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void,
/**
* Only run this test
*
@@ -462,7 +492,11 @@ declare var it: {
* @param {Function} Test
* @param {number} Timeout for the test, in milliseconds.
*/
only(name: string, fn?: (done: () => void) => ?Promise<mixed>, timeout?: number): void,
only(
name: string,
fn?: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void,
/**
* Skip running this test
*
@@ -470,7 +504,11 @@ declare var it: {
* @param {Function} Test
* @param {number} Timeout for the test, in milliseconds.
*/
skip(name: string, fn?: (done: () => void) => ?Promise<mixed>, timeout?: number): void,
skip(
name: string,
fn?: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void,
/**
* Run the test concurrently
*
@@ -478,12 +516,16 @@ declare var it: {
* @param {Function} Test
* @param {number} Timeout for the test, in milliseconds.
*/
concurrent(name: string, fn?: (done: () => void) => ?Promise<mixed>, timeout?: number): void,
concurrent(
name: string,
fn?: (done: () => void) => ?Promise<mixed>,
timeout?: number
): void
};
declare function fit(
name: string,
fn: (done: () => void) => ?Promise<mixed>,
timeout?: number,
timeout?: number
): void;
/** An individual test unit */
declare var test: typeof it;
@@ -523,7 +565,7 @@ declare function spyOn(value: mixed, method: string): Object;
declare var jest: JestObjectType;
/**
* The global Jamine object, this is generally not exposed as the public API,
* The global Jasmine object, this is generally not exposed as the public API,
* using features inside here could break in later versions of Jest.
*/
declare var jasmine: {

View File

@@ -1,5 +1,5 @@
// flow-typed signature: bd52927dcfdd08c54751906ebaf7cfa1
// flow-typed version: <<STUB>>/react-native-scripts_v^1.3.1/flow_v0.53.0
// flow-typed signature: 42d8cd2e84e894c09d28f891fef9f01d
// flow-typed version: <<STUB>>/react-native-scripts_v^1.5.0/flow_v0.61.0
/**
* This is an autogenerated libdef stub for:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
// flow-typed signature: 2d946f2ec4aba5210b19d053c411a59d
// flow-typed version: 95b3e05165/react-test-renderer_v16.x.x/flow_>=v0.47.x
// Type definitions for react-test-renderer 16.x.x
// Ported from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-test-renderer
type ReactTestRendererJSON = {
type: string,
props: { [propName: string]: any },
children: null | ReactTestRendererJSON[]
};
type ReactTestRendererTree = ReactTestRendererJSON & {
nodeType: "component" | "host",
instance: any,
rendered: null | ReactTestRendererTree
};
type ReactTestInstance = {
instance: any,
type: string,
props: { [propName: string]: any },
parent: null | ReactTestInstance,
children: Array<ReactTestInstance | string>,
find(predicate: (node: ReactTestInstance) => boolean): ReactTestInstance,
findByType(type: React$ElementType): ReactTestInstance,
findByProps(props: { [propName: string]: any }): ReactTestInstance,
findAll(
predicate: (node: ReactTestInstance) => boolean,
options?: { deep: boolean }
): ReactTestInstance[],
findAllByType(
type: React$ElementType,
options?: { deep: boolean }
): ReactTestInstance[],
findAllByProps(
props: { [propName: string]: any },
options?: { deep: boolean }
): ReactTestInstance[]
};
type ReactTestRenderer = {
toJSON(): null | ReactTestRendererJSON,
toTree(): null | ReactTestRendererTree,
unmount(nextElement?: React$Element<any>): void,
update(nextElement: React$Element<any>): void,
getInstance(): null | ReactTestInstance,
root: ReactTestInstance
};
type TestRendererOptions = {
createNodeMock(element: React$Element<any>): any
};
declare module "react-test-renderer" {
declare function create(
nextElement: React$Element<any>,
options?: TestRendererOptions
): ReactTestRenderer;
}

View File

@@ -1,11 +1,13 @@
/* @flow */
import React from 'react';
import { Constants, ScreenOrientation } from 'expo';
import { Asset, Constants, ScreenOrientation } from 'expo';
ScreenOrientation.allow(ScreenOrientation.Orientation.ALL);
import {
Animated,
Image,
Platform,
ScrollView,
StyleSheet,
@@ -14,9 +16,8 @@ import {
StatusBar,
View,
} from 'react-native';
import { SafeAreaView, StackNavigator } from 'react-navigation';
import { SafeAreaView, createStackNavigator } from 'react-navigation';
import Banner from './Banner';
import CustomTabs from './CustomTabs';
import CustomTransitioner from './CustomTransitioner';
import Drawer from './Drawer';
@@ -25,45 +26,68 @@ import TabsInDrawer from './TabsInDrawer';
import ModalStack from './ModalStack';
import StacksInTabs from './StacksInTabs';
import StacksOverTabs from './StacksOverTabs';
import StacksOverTopTabs from './StacksOverTopTabs';
import StacksWithKeys from './StacksWithKeys';
import InactiveStack from './InactiveStack';
import StackWithCustomHeaderBackImage from './StackWithCustomHeaderBackImage';
import SimpleStack from './SimpleStack';
import StackWithHeaderPreset from './StackWithHeaderPreset';
import StackWithTranslucentHeader from './StackWithTranslucentHeader';
import SimpleTabs from './SimpleTabs';
import TabAnimations from './TabAnimations';
import SwitchWithStacks from './SwitchWithStacks';
import TabsWithNavigationFocus from './TabsWithNavigationFocus';
import TabsWithNavigationEvents from './TabsWithNavigationEvents';
import KeyboardHandlingExample from './KeyboardHandlingExample';
const ExampleRoutes = {
const ExampleInfo = {
SimpleStack: {
name: 'Stack Example',
description: 'A card stack',
screen: SimpleStack,
},
SwitchWithStacks: {
name: 'Switch between routes',
description: 'Jump between routes',
},
InactiveStack: {
name: 'Navigate idempotently to stacks in inactive routes',
description:
'An inactive route in a stack should be given the opportunity to handle actions',
},
StackWithCustomHeaderBackImage: {
name: 'Custom header back image',
description: 'Stack with custom header back image',
},
SimpleTabs: {
name: 'Tabs Example',
description: 'Tabs following platform conventions',
screen: SimpleTabs,
},
Drawer: {
name: 'Drawer Example',
description: 'Android-style drawer navigation',
screen: Drawer,
},
StackWithHeaderPreset: {
name: 'UIKit-style Header Transitions',
description: 'Masked back button and sliding header items. iOS only.',
},
StackWithTranslucentHeader: {
name: 'Translucent Header',
description: 'Render arbitrary translucent content in header background.',
},
// MultipleDrawer: {
// name: 'Multiple Drawer Example',
// description: 'Add any drawer you need',
// screen: MultipleDrawer,
// },
TabsInDrawer: {
name: 'Drawer + Tabs Example',
description: 'A drawer combined with tabs',
screen: TabsInDrawer,
},
CustomTabs: {
name: 'Custom Tabs',
description: 'Custom tabs with tab router',
screen: CustomTabs,
},
CustomTransitioner: {
name: 'Custom Transitioner',
description: 'Custom transitioner with stack router',
screen: CustomTransitioner,
},
ModalStack: {
name:
@@ -74,80 +98,230 @@ const ExampleRoutes = {
Platform.OS === 'ios'
? 'Stack navigation with modals'
: 'Dynamically showing and hiding the header',
screen: ModalStack,
},
StacksInTabs: {
name: 'Stacks in Tabs',
description: 'Nested stack navigation in tabs',
screen: StacksInTabs,
},
StacksOverTabs: {
name: 'Stacks over Tabs',
description: 'Nested stack navigation that pushes on top of tabs',
screen: StacksOverTabs,
},
StacksOverTopTabs: {
name: 'Stacks with non-standard header height',
description: 'Tab navigator in stack with custom header heights',
},
StacksWithKeys: {
name: 'Link in Stack with keys',
description: 'Use keys to link between screens',
},
LinkStack: {
name: 'Link in Stack',
description: 'Deep linking into a route in stack',
screen: SimpleStack,
path: 'people/Jordan',
},
LinkTabs: {
name: 'Link to Settings Tab',
description: 'Deep linking into a route in tab',
screen: SimpleTabs,
path: 'settings',
},
TabAnimations: {
name: 'Animated Tabs Example',
description: 'Tab transitions have custom animations',
screen: TabAnimations,
TabsWithNavigationFocus: {
name: 'withNavigationFocus',
description: 'Receive the focus prop to know when a screen is focused',
},
TabsWithNavigationEvents: {
name: 'NavigationEvents',
description:
'Declarative NavigationEvents component to subscribe to navigation events',
},
KeyboardHandlingExample: {
name: 'Keyboard Handling Example',
description:
'Demo automatic handling of keyboard showing/hiding inside StackNavigator',
},
};
class MainScreen extends React.Component<*> {
const ExampleRoutes = {
SimpleStack,
SwitchWithStacks,
SimpleTabs: SimpleTabs,
Drawer: Drawer,
// MultipleDrawer: {
// screen: MultipleDrawer,
// },
StackWithCustomHeaderBackImage: StackWithCustomHeaderBackImage,
...Platform.select({
ios: {
StackWithHeaderPreset: StackWithHeaderPreset,
},
android: {},
}),
StackWithTranslucentHeader: StackWithTranslucentHeader,
TabsInDrawer: TabsInDrawer,
CustomTabs: CustomTabs,
CustomTransitioner: CustomTransitioner,
ModalStack: ModalStack,
StacksWithKeys: StacksWithKeys,
StacksInTabs: StacksInTabs,
StacksOverTabs: StacksOverTabs,
StacksOverTopTabs: StacksOverTopTabs,
LinkStack: {
screen: SimpleStack,
path: 'people/Jordan',
},
LinkTabs: {
screen: SimpleTabs,
path: 'settings',
},
TabsWithNavigationFocus,
TabsWithNavigationEvents,
KeyboardHandlingExample,
// This is commented out because it's rarely useful
// InactiveStack,
};
type State = {
scrollY: Animated.Value,
};
class MainScreen extends React.Component<any, State> {
state = {
scrollY: new Animated.Value(0),
};
componentDidMount() {
Asset.fromModule(
require('react-navigation/src/views/assets/back-icon-mask.png')
).downloadAsync();
Asset.fromModule(
require('react-navigation/src/views/assets/back-icon.png')
).downloadAsync();
}
render() {
const { navigation } = this.props;
const scale = this.state.scrollY.interpolate({
inputRange: [-450, 0, 100],
outputRange: [2, 1, 0.8],
extrapolate: 'clamp',
});
const translateY = this.state.scrollY.interpolate({
inputRange: [-450, 0, 100],
outputRange: [-150, 0, 40],
});
const opacity = this.state.scrollY.interpolate({
inputRange: [0, 50],
outputRange: [1, 0],
extrapolate: 'clamp',
});
const underlayOpacity = this.state.scrollY.interpolate({
inputRange: [0, 50],
outputRange: [0, 1],
extrapolate: 'clamp',
});
const backgroundScale = this.state.scrollY.interpolate({
inputRange: [-450, 0],
outputRange: [3, 1],
extrapolate: 'clamp',
});
const backgroundTranslateY = this.state.scrollY.interpolate({
inputRange: [-450, 0],
outputRange: [0, 0],
});
return (
<View style={{ flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<Banner />
{Object.keys(ExampleRoutes).map((routeName: string) => (
<TouchableOpacity
key={routeName}
onPress={() => {
const { path, params, screen } = ExampleRoutes[routeName];
const { router } = screen;
const action =
path && router.getActionForPathAndParams(path, params);
navigation.navigate(routeName, {}, action);
}}
<Animated.ScrollView
style={{ flex: 1 }}
scrollEventThrottle={1}
onScroll={Animated.event(
[
{
nativeEvent: { contentOffset: { y: this.state.scrollY } },
},
],
{ useNativeDriver: true }
)}
>
<Animated.View
style={[
styles.backgroundUnderlay,
{
transform: [
{ scale: backgroundScale },
{ translateY: backgroundTranslateY },
],
},
]}
/>
<Animated.View
style={{ opacity, transform: [{ scale }, { translateY }] }}
>
<SafeAreaView
style={styles.bannerContainer}
forceInset={{ top: 'always', bottom: 'never' }}
>
<SafeAreaView
style={styles.itemContainer}
forceInset={{ vertical: 'never' }}
>
<View style={styles.item}>
<Text style={styles.title}>
{ExampleRoutes[routeName].name}
</Text>
<Text style={styles.description}>
{ExampleRoutes[routeName].description}
</Text>
</View>
</SafeAreaView>
</TouchableOpacity>
))}
</ScrollView>
<View style={styles.banner}>
<Image
source={require('./assets/NavLogo.png')}
style={styles.bannerImage}
/>
<Text style={styles.bannerTitle}>
React Navigation Examples
</Text>
</View>
</SafeAreaView>
</Animated.View>
<SafeAreaView forceInset={{ bottom: 'always', horizontal: 'never' }}>
<View style={{ backgroundColor: '#fff' }}>
{Object.keys(ExampleRoutes).map((routeName: string) => (
<TouchableOpacity
key={routeName}
onPress={() => {
let route = ExampleRoutes[routeName];
if (route.screen || route.path || route.params) {
const { path, params, screen } = route;
const { router } = screen;
const action =
path && router.getActionForPathAndParams(path, params);
navigation.navigate(routeName, {}, action);
} else {
navigation.navigate(routeName);
}
}}
>
<SafeAreaView
style={styles.itemContainer}
forceInset={{ veritcal: 'never', bottom: 'never' }}
>
<View style={styles.item}>
<Text style={styles.title}>
{ExampleInfo[routeName].name}
</Text>
<Text style={styles.description}>
{ExampleInfo[routeName].description}
</Text>
</View>
</SafeAreaView>
</TouchableOpacity>
))}
</View>
</SafeAreaView>
</Animated.ScrollView>
<StatusBar barStyle="light-content" />
<View style={styles.statusBarUnderlay} />
<Animated.View
style={[styles.statusBarUnderlay, { opacity: underlayOpacity }]}
/>
</View>
);
}
}
const AppNavigator = StackNavigator(
const AppNavigator = createStackNavigator(
{
...ExampleRoutes,
Index: {
@@ -166,7 +340,7 @@ const AppNavigator = StackNavigator(
}
);
export default () => <AppNavigator />;
export default AppNavigator;
const styles = StyleSheet.create({
item: {
@@ -202,4 +376,35 @@ const styles = StyleSheet.create({
fontSize: 13,
color: '#999',
},
backgroundUnderlay: {
backgroundColor: '#673ab7',
position: 'absolute',
top: -100,
height: 300,
left: 0,
right: 0,
},
bannerContainer: {
// backgroundColor: '#673ab7',
alignItems: 'center',
},
banner: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
},
bannerImage: {
width: 36,
height: 36,
resizeMode: 'contain',
tintColor: '#fff',
margin: 8,
},
bannerTitle: {
fontSize: 18,
fontWeight: '200',
color: '#fff',
marginVertical: 8,
marginRight: 5,
},
});

View File

@@ -8,7 +8,7 @@ import { SafeAreaView } from 'react-navigation';
const Banner = () => (
<SafeAreaView
style={styles.bannerContainer}
forceInset={{ vertical: 'never' }}
forceInset={{ top: 'always' }}
>
<View style={styles.banner}>
<Image source={require('./assets/NavLogo.png')} style={styles.image} />

View File

@@ -4,7 +4,6 @@
import React from 'react';
import {
Button,
Platform,
ScrollView,
StyleSheet,
@@ -18,9 +17,9 @@ import {
createNavigationContainer,
SafeAreaView,
TabRouter,
addNavigationHelpers,
} from 'react-navigation';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
@@ -66,19 +65,14 @@ const CustomTabBar = ({ navigation }) => {
);
};
const CustomTabView = ({ router, navigation }) => {
const CustomTabView = ({ descriptors, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForRouteName(routes[index].routeName);
const descriptor = descriptors[routes[index].key];
const ActiveScreen = descriptor.getComponent();
return (
<SafeAreaView forceInset={{ top: 'always' }}>
<CustomTabBar navigation={navigation} />
<ActiveScreen
navigation={addNavigationHelpers({
dispatch: navigation.dispatch,
state: routes[index],
})}
screenProps={{}}
/>
<ActiveScreen navigation={descriptor.navigation} />
</SafeAreaView>
);
};
@@ -105,7 +99,7 @@ const CustomTabRouter = TabRouter(
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
createNavigator(CustomTabView, CustomTabRouter, {})
);
const styles = StyleSheet.create({

View File

@@ -1,7 +1,6 @@
import React, { Component, PropTypes } from 'react';
import {
Animated,
Button,
Easing,
Image,
Platform,
@@ -14,10 +13,10 @@ import {
SafeAreaView,
StackRouter,
createNavigationContainer,
addNavigationHelpers,
createNavigator,
} from 'react-navigation';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<SafeAreaView forceInset={{ top: 'always' }}>
@@ -45,11 +44,12 @@ const MySettingsScreen = ({ navigation }) => (
class CustomNavigationView extends Component {
render() {
const { navigation, router } = this.props;
const { navigation, router, descriptors } = this.props;
return (
<Transitioner
configureTransition={this._configureTransition}
descriptors={descriptors}
navigation={navigation}
render={this._render}
/>
@@ -86,16 +86,10 @@ class CustomNavigationView extends Component {
transform: [{ scale: animatedValue }],
};
// The prop `router` is populated when we call `createNavigator`.
const Scene = router.getComponentForRouteName(scene.route.routeName);
const Scene = scene.descriptor.getComponent();
return (
<Animated.View key={index} style={[styles.view, animation]}>
<Scene
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
<Scene navigation={scene.descriptor.navigation} />
</Animated.View>
);
};
@@ -107,7 +101,7 @@ const CustomRouter = StackRouter({
});
const CustomTransitioner = createNavigationContainer(
createNavigator(CustomRouter)(CustomNavigationView)
createNavigator(CustomNavigationView, CustomRouter, {})
);
export default CustomTransitioner;

View File

@@ -3,18 +3,24 @@
*/
import React from 'react';
import { Button, Platform, ScrollView, StatusBar } from 'react-native';
import { DrawerNavigator, SafeAreaView } from 'react-navigation';
import { Platform, ScrollView, StatusBar } from 'react-native';
import {
createStackNavigator,
createDrawerNavigator,
SafeAreaView,
} from 'react-navigation';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<SafeAreaView forceInset={{ top: 'always' }}>
<SampleText>{banner}</SampleText>
<Button onPress={() => navigation.openDrawer()} title="Open drawer" />
<Button
onPress={() => navigation.navigate('DrawerOpen')}
title="Open drawer"
onPress={() => navigation.navigate('Email')}
title="Open other screen"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
@@ -26,6 +32,26 @@ const InboxScreen = ({ navigation }) => (
<MyNavScreen banner={'Inbox Screen'} navigation={navigation} />
);
InboxScreen.navigationOptions = {
headerTitle: 'Inbox',
};
const EmailScreen = ({ navigation }) => (
<MyNavScreen banner={'Email Screen'} navigation={navigation} />
);
const DraftsScreen = ({ navigation }) => (
<MyNavScreen banner={'Drafts Screen'} navigation={navigation} />
);
DraftsScreen.navigationOptions = {
headerTitle: 'Drafts',
};
const InboxStack = createStackNavigator({
Inbox: { screen: InboxScreen },
Email: { screen: EmailScreen },
});
InboxStack.navigationOptions = {
drawerLabel: 'Inbox',
drawerIcon: ({ tintColor }) => (
<MaterialIcons
@@ -36,31 +62,30 @@ InboxScreen.navigationOptions = {
),
};
const DraftsScreen = ({ navigation }) => (
<MyNavScreen banner={'Drafts Screen'} navigation={navigation} />
);
DraftsScreen.navigationOptions = {
const DraftsStack = createStackNavigator({
Drafts: { screen: DraftsScreen },
Email: { screen: EmailScreen },
});
DraftsStack.navigationOptions = {
drawerLabel: 'Drafts',
drawerIcon: ({ tintColor }) => (
<MaterialIcons name="drafts" size={24} style={{ color: tintColor }} />
),
};
const DrawerExample = DrawerNavigator(
const DrawerExample = createDrawerNavigator(
{
Inbox: {
path: '/',
screen: InboxScreen,
screen: InboxStack,
},
Drafts: {
path: '/sent',
screen: DraftsScreen,
screen: DraftsStack,
},
},
{
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
initialRouteName: 'Drafts',
contentOptions: {
activeTintColor: '#e91e63',

View File

@@ -0,0 +1,96 @@
import React from 'react';
import { Button, Text, StatusBar, View, StyleSheet } from 'react-native';
import {
SafeAreaView,
createStackNavigator,
createSwitchNavigator,
NavigationActions,
} from 'react-navigation';
const runSubRoutes = navigation => {
navigation.dispatch(NavigationActions.navigate({ routeName: 'First2' }));
navigation.dispatch(NavigationActions.navigate({ routeName: 'Second2' }));
navigation.dispatch(NavigationActions.navigate({ routeName: 'First2' }));
};
const runSubRoutesWithIntermediate = navigation => {
navigation.dispatch(toFirst1);
navigation.dispatch(toSecond2);
navigation.dispatch(toFirst);
navigation.dispatch(toFirst2);
};
const runSubAction = navigation => {
navigation.dispatch(toFirst2);
navigation.dispatch(toSecond2);
navigation.dispatch(toFirstChild1);
};
const DummyScreen = ({ routeName, navigation, style }) => {
return (
<SafeAreaView
style={[
StyleSheet.absoluteFill,
{
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
},
style,
]}
>
<Text style={{ fontWeight: '800' }}>
{routeName}({navigation.state.key})
</Text>
<View>
<Button title="back" onPress={() => navigation.goBack()} />
<Button title="dismiss" onPress={() => navigation.dismiss()} />
<Button
title="between sub-routes"
onPress={() => runSubRoutes(navigation)}
/>
<Button
title="between sub-routes (with intermediate)"
onPress={() => runSubRoutesWithIntermediate(navigation)}
/>
<Button
title="with sub-action"
onPress={() => runSubAction(navigation)}
/>
</View>
<StatusBar barStyle="default" />
</SafeAreaView>
);
};
const createDummyScreen = routeName => {
const BoundDummyScreen = props => DummyScreen({ ...props, routeName });
return BoundDummyScreen;
};
const toFirst = NavigationActions.navigate({ routeName: 'First' });
const toFirst1 = NavigationActions.navigate({ routeName: 'First1' });
const toFirst2 = NavigationActions.navigate({ routeName: 'First2' });
const toSecond2 = NavigationActions.navigate({ routeName: 'Second2' });
const toFirstChild1 = NavigationActions.navigate({
routeName: 'First',
action: NavigationActions.navigate({ routeName: 'First1' }),
});
export default createStackNavigator(
{
Other: createDummyScreen('Leaf'),
First: createStackNavigator({
First1: createDummyScreen('First1'),
First2: createDummyScreen('First2'),
}),
Second: createStackNavigator({
Second1: createDummyScreen('Second1'),
Second2: createDummyScreen('Second2'),
}),
},
{
headerMode: 'none',
}
);

View File

@@ -0,0 +1,63 @@
import React from 'react';
import { StatusBar, View, TextInput, InteractionManager } from 'react-native';
import { createStackNavigator, withNavigationFocus } from 'react-navigation';
import { Button } from './commonComponents/ButtonWithMargin';
class ScreenOne extends React.Component {
static navigationOptions = {
title: 'Home',
};
render() {
const { navigation } = this.props;
return (
<View style={{ paddingTop: 30 }}>
<Button
onPress={() => navigation.push('ScreenTwo')}
title="Push screen with focused text input"
/>
<Button onPress={() => navigation.goBack(null)} title="Go Home" />
<StatusBar barStyle="default" />
</View>
);
}
}
class ScreenTwo extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: navigation.getParam('inputValue', 'Screen w/ Input'),
});
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this._textInput.focus();
});
}
render() {
const { navigation } = this.props;
return (
<View style={{ paddingTop: 30 }}>
<View style={{ alignSelf: 'center', paddingVertical: 20 }}>
<TextInput
ref={c => (this._textInput = c)}
onChangeText={inputValue => navigation.setParams({ inputValue })}
style={{
backgroundColor: 'white',
height: 24,
width: 150,
borderColor: '#555',
borderWidth: 1,
}}
/>
</View>
<Button onPress={() => navigation.pop()} title="Pop" />
</View>
);
}
}
export default createStackNavigator({
ScreenOne,
ScreenTwo: withNavigationFocus(ScreenTwo),
});

View File

@@ -3,12 +3,13 @@
*/
import React from 'react';
import { Button, ScrollView, StatusBar, Text } from 'react-native';
import { SafeAreaView, StackNavigator } from 'react-navigation';
import { ScrollView, StatusBar, Text } from 'react-native';
import { SafeAreaView, createStackNavigator } from 'react-navigation';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<ScrollView>
<SafeAreaView
forceInset={{
top: navigation.state.routeName === 'HeaderTest' ? 'always' : 'never',
@@ -31,7 +32,8 @@ const MyNavScreen = ({ navigation, banner }) => (
headerVisible:
!navigation.state.params ||
!navigation.state.params.headerVisible,
})}
})
}
/>
)}
<Button onPress={() => navigation.goBack(null)} title="Go back" />
@@ -57,7 +59,7 @@ MyProfileScreen.navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile!`,
});
const ProfileNavigator = StackNavigator(
const ProfileNavigator = createStackNavigator(
{
Home: {
screen: MyHomeScreen,
@@ -69,8 +71,9 @@ const ProfileNavigator = StackNavigator(
},
{
navigationOptions: {
header: null,
headerLeft: null,
},
mode: 'modal',
}
);
@@ -86,17 +89,17 @@ MyHeaderTestScreen.navigationOptions = ({ navigation }) => {
};
};
const ModalStack = StackNavigator(
const ModalStack = createStackNavigator(
{
Home: {
screen: MyHomeScreen,
},
ProfileNavigator: {
screen: ProfileNavigator,
},
HeaderTest: { screen: MyHeaderTestScreen },
},
{
navigationOptions: {
header: null,
},
mode: 'modal',
}
);

View File

@@ -3,18 +3,16 @@
*/
import React from 'react';
import { Button, Platform, ScrollView, StyleSheet } from 'react-native';
import { DrawerNavigator } from 'react-navigation';
import { Platform, ScrollView, StyleSheet } from 'react-native';
import { createDrawerNavigator } from 'react-navigation';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView style={styles.container}>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('DrawerOpen')}
title="Open drawer"
/>
<Button onPress={() => navigation.openDrawer()} title="Open drawer" />
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</ScrollView>
);
@@ -43,7 +41,7 @@ DraftsScreen.navigationOptions = {
),
};
const DrawerExample = DrawerNavigator(
const DrawerExample = createDrawerNavigator(
{
Inbox: {
path: '/',
@@ -55,9 +53,6 @@ const DrawerExample = DrawerNavigator(
},
},
{
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
initialRouteName: 'Drafts',
contentOptions: {
activeTintColor: '#e91e63',
@@ -65,14 +60,10 @@ const DrawerExample = DrawerNavigator(
}
);
const MainDrawerExample = DrawerNavigator({
const MainDrawerExample = createDrawerNavigator({
Drafts: {
screen: DrawerExample,
},
}, {
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle',
});
const styles = StyleSheet.create({

View File

@@ -2,49 +2,211 @@
* @flow
*/
import React from 'react';
import { Button, ScrollView, StatusBar } from 'react-native';
import { StackNavigator, SafeAreaView } from 'react-navigation';
import type {
NavigationScreenProp,
NavigationState,
NavigationStateRoute,
NavigationEventSubscription,
} from 'react-navigation';
import * as React from 'react';
import { Platform, ScrollView, StatusBar } from 'react-native';
import {
createStackNavigator,
SafeAreaView,
withNavigation,
NavigationActions,
StackActions,
} from 'react-navigation';
import invariant from 'invariant';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
import { HeaderButtons } from './commonComponents/HeaderButtons';
const MyNavScreen = ({ navigation, banner }) => (
<SafeAreaView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jane' })}
title="Go to a profile screen"
/>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Go to a photos screen"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
const DEBUG = false;
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen banner="Home Screen" navigation={navigation} />
);
MyHomeScreen.navigationOptions = {
title: 'Welcome',
type MyNavScreenProps = {
navigation: NavigationScreenProp<NavigationState>,
banner: React.Node,
};
const MyPhotosScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.name}'s Photos`}
navigation={navigation}
/>
);
MyPhotosScreen.navigationOptions = {
title: 'Photos',
type BackButtonProps = {
navigation: NavigationScreenProp<NavigationStateRoute>,
};
class MyBackButton extends React.Component<BackButtonProps, any> {
render() {
return (
<HeaderButtons>
<HeaderButtons.Item title="Back" onPress={this._navigateBack} />
</HeaderButtons>
);
}
_navigateBack = () => {
this.props.navigation.goBack(null);
};
}
const MyBackButtonWithNavigation = withNavigation(MyBackButton);
class MyNavScreen extends React.Component<MyNavScreenProps> {
render() {
const { navigation, banner } = this.props;
const { push, replace, popToTop, pop, dismiss } = navigation;
invariant(
push && replace && popToTop && pop && dismiss,
'missing action creators for StackNavigator'
);
return (
<SafeAreaView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => push('Profile', { name: 'Jane' })}
title="Push a profile screen"
/>
<Button
onPress={() =>
navigation.dispatch(
StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'Photos',
params: { name: 'Jane' },
}),
],
})
)
}
title="Reset photos"
/>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Navigate to a photos screen"
/>
<Button
onPress={() => replace('Profile', { name: 'Lucy' })}
title="Replace with profile"
/>
<Button onPress={() => popToTop()} title="Pop to top" />
<Button onPress={() => pop()} title="Pop" />
<Button
onPress={() => {
if (navigation.goBack()) {
console.log('goBack handled');
} else {
console.log('goBack unhandled');
}
}}
title="Go back"
/>
<Button onPress={() => dismiss()} title="Dismiss" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
type MyHomeScreenProps = {
navigation: NavigationScreenProp<NavigationState>,
};
class MyHomeScreen extends React.Component<MyHomeScreenProps> {
static navigationOptions = {
title: 'Welcome',
};
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onWF);
this._s1 = this.props.navigation.addListener('didFocus', this._onDF);
this._s2 = this.props.navigation.addListener('willBlur', this._onWB);
this._s3 = this.props.navigation.addListener('didBlur', this._onDB);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onWF = a => {
DEBUG && console.log('_willFocus HomeScreen', a);
};
_onDF = a => {
DEBUG && console.log('_didFocus HomeScreen', a);
};
_onWB = a => {
DEBUG && console.log('_willBlur HomeScreen', a);
};
_onDB = a => {
DEBUG && console.log('_didBlur HomeScreen', a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="Home Screen" navigation={navigation} />;
}
}
type MyPhotosScreenProps = {
navigation: NavigationScreenProp<NavigationState>,
};
class MyPhotosScreen extends React.Component<MyPhotosScreenProps> {
static navigationOptions = {
title: 'Photos',
headerLeft: <MyBackButtonWithNavigation />,
};
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onWF);
this._s1 = this.props.navigation.addListener('didFocus', this._onDF);
this._s2 = this.props.navigation.addListener('willBlur', this._onWB);
this._s3 = this.props.navigation.addListener('didBlur', this._onDB);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onWF = a => {
DEBUG && console.log('_willFocus PhotosScreen', a);
};
_onDF = a => {
DEBUG && console.log('_didFocus PhotosScreen', a);
};
_onWB = a => {
DEBUG && console.log('_willBlur PhotosScreen', a);
};
_onDB = a => {
DEBUG && console.log('_didBlur PhotosScreen', a);
};
render() {
const { navigation } = this.props;
return (
<MyNavScreen
banner={`${navigation.getParam('name')}'s Photos`}
navigation={navigation}
/>
);
}
}
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.mode === 'edit'
? 'Now Editing '
: ''}${navigation.state.params.name}'s Profile`}
banner={`${
navigation.getParam('mode') === 'edit' ? 'Now Editing ' : ''
}${navigation.getParam('name')}'s Profile`}
navigation={navigation}
/>
);
@@ -54,31 +216,40 @@ MyProfileScreen.navigationOptions = props => {
const { state, setParams } = navigation;
const { params } = state;
return {
headerBackImage: params.headerBackImage,
headerTitle: `${params.name}'s Profile!`,
// Render a button on the right side of the header.
// When pressed switches the screen to edit mode.
headerRight: (
<Button
title={params.mode === 'edit' ? 'Done' : 'Edit'}
onPress={() =>
setParams({ mode: params.mode === 'edit' ? '' : 'edit' })}
/>
<HeaderButtons>
<HeaderButtons.Item
title={params.mode === 'edit' ? 'Done' : 'Edit'}
onPress={() =>
setParams({ mode: params.mode === 'edit' ? '' : 'edit' })
}
/>
</HeaderButtons>
),
};
};
const SimpleStack = StackNavigator({
Home: {
screen: MyHomeScreen,
const SimpleStack = createStackNavigator(
{
Home: {
screen: MyHomeScreen,
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
});
{
// headerLayoutPreset: 'center',
}
);
export default SimpleStack;

View File

@@ -2,11 +2,17 @@
* @flow
*/
import type {
NavigationScreenProp,
NavigationEventSubscription,
} from 'react-navigation';
import React from 'react';
import { Button, Platform, ScrollView, StatusBar, View } from 'react-native';
import { SafeAreaView, TabNavigator } from 'react-navigation';
import { Platform, ScrollView, StatusBar, View } from 'react-native';
import { SafeAreaView, createBottomTabNavigator } from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<SafeAreaView forceInset={{ horizontal: 'always', top: 'always' }}>
@@ -43,35 +49,85 @@ MyHomeScreen.navigationOptions = {
),
};
const MyPeopleScreen = ({ navigation }) => (
<MyNavScreen banner="People Tab" navigation={navigation} />
);
MyPeopleScreen.navigationOptions = {
tabBarLabel: 'People',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-people' : 'ios-people-outline'}
size={26}
style={{ color: tintColor }}
/>
),
type MyPeopleScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyPeopleScreen extends React.Component<MyPeopleScreenProps> {
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
const MyChatScreen = ({ navigation }) => (
<MyNavScreen banner="Chat Tab" navigation={navigation} />
);
static navigationOptions = {
tabBarLabel: 'People',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-people' : 'ios-people-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onEvent);
this._s1 = this.props.navigation.addListener('didFocus', this._onEvent);
this._s2 = this.props.navigation.addListener('willBlur', this._onEvent);
this._s3 = this.props.navigation.addListener('didBlur', this._onEvent);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onEvent = a => {
console.log('EVENT ON PEOPLE TAB', a.type, a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="People Tab" navigation={navigation} />;
}
}
MyChatScreen.navigationOptions = {
tabBarLabel: 'Chat',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-chatboxes' : 'ios-chatboxes-outline'}
size={26}
style={{ color: tintColor }}
/>
),
type MyChatScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyChatScreen extends React.Component<MyChatScreenProps> {
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
static navigationOptions = {
tabBarLabel: 'Chat',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-chatboxes' : 'ios-chatboxes-outline'}
size={26}
style={{ color: tintColor }}
/>
),
};
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onEvent);
this._s1 = this.props.navigation.addListener('didFocus', this._onEvent);
this._s2 = this.props.navigation.addListener('willBlur', this._onEvent);
this._s3 = this.props.navigation.addListener('didBlur', this._onEvent);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onEvent = a => {
console.log('EVENT ON CHAT TAB', a.type, a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="Chat Tab" navigation={navigation} />;
}
}
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Tab" navigation={navigation} />
@@ -88,7 +144,7 @@ MySettingsScreen.navigationOptions = {
),
};
const SimpleTabs = TabNavigator(
const SimpleTabs = createBottomTabNavigator(
{
Home: {
screen: MyHomeScreen,
@@ -109,9 +165,40 @@ const SimpleTabs = TabNavigator(
},
{
tabBarOptions: {
activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff',
activeTintColor: '#e91e63',
},
}
);
export default SimpleTabs;
type SimpleTabsContainerProps = {
navigation: NavigationScreenProp<*>,
};
class SimpleTabsContainer extends React.Component<SimpleTabsContainerProps> {
static router = SimpleTabs.router;
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onAction);
this._s1 = this.props.navigation.addListener('didFocus', this._onAction);
this._s2 = this.props.navigation.addListener('willBlur', this._onAction);
this._s3 = this.props.navigation.addListener('didBlur', this._onAction);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onAction = a => {
console.log('TABS EVENT', a.type, a);
};
render() {
return <SimpleTabs navigation={this.props.navigation} />;
}
}
export default SimpleTabsContainer;

View File

@@ -0,0 +1,145 @@
/**
* @flow
*/
import type { NavigationScreenProp } from 'react-navigation';
import * as React from 'react';
import { Image, Button, StatusBar, StyleSheet } from 'react-native';
import { createStackNavigator, SafeAreaView } from 'react-navigation';
import SampleText from './SampleText';
type MyNavScreenProps = {
navigation: NavigationScreenProp<*>,
banner: React.Node,
};
class MyCustomHeaderBackImage extends React.Component<any, any> {
render() {
const source = require('./assets/back.png');
return (
<Image
source={source}
style={[styles.myCustomHeaderBackImage, this.props.style]}
/>
);
}
}
class MyNavScreen extends React.Component<MyNavScreenProps> {
render() {
const { navigation, banner } = this.props;
return (
<SafeAreaView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Navigate to a photos screen"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
type MyHomeScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyHomeScreen extends React.Component<MyHomeScreenProps> {
static navigationOptions = {
title: 'Welcome',
headerBackTitle: null,
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="Home Screen" navigation={navigation} />;
}
}
type MyPhotosScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyPhotosScreen extends React.Component<MyPhotosScreenProps> {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.name}'s photos`,
headerBackTitle: null,
});
render() {
const { navigation } = this.props;
return (
<SafeAreaView>
<SampleText>{`${navigation.state.params.name}'s Photos`}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jane' })}
title="Navigate to a profile screen"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
type MyProfileScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyProfileScreen extends React.Component<MyProfileScreenProps> {
static navigationOptions = ({ navigation }) => ({
title: 'Profile',
headerBackImage: (
<MyCustomHeaderBackImage style={styles.myCustomHeaderBackImageAlt} />
),
});
render() {
const { navigation } = this.props;
return (
<SafeAreaView>
<SampleText>{`${navigation.state.params.name}'s Profile`}</SampleText>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
const StackWithCustomHeaderBackImage = createStackNavigator(
{
Home: {
screen: MyHomeScreen,
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
Profile: {
path: 'profile/:name',
screen: MyProfileScreen,
},
},
{
navigationOptions: {
headerBackImage: MyCustomHeaderBackImage,
},
}
);
export default StackWithCustomHeaderBackImage;
const styles = StyleSheet.create({
myCustomHeaderBackImage: {
height: 14.5,
width: 24,
marginLeft: 9,
marginRight: 12,
marginVertical: 12,
resizeMode: 'contain',
},
myCustomHeaderBackImageAlt: {
tintColor: '#f00',
},
});

View File

@@ -0,0 +1,123 @@
/**
* @flow
*/
import type { NavigationScreenProp } from 'react-navigation';
import * as React from 'react';
import { ScrollView, StatusBar } from 'react-native';
import { createStackNavigator, SafeAreaView } from 'react-navigation';
import invariant from 'invariant';
import { Button } from './commonComponents/ButtonWithMargin';
type NavScreenProps = {
navigation: NavigationScreenProp<*>,
};
class HomeScreen extends React.Component<NavScreenProps> {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigation } = this.props;
const { push } = navigation;
invariant(push, 'missing `push` action creator for StackNavigator');
return (
<SafeAreaView style={{ paddingTop: 30 }}>
<Button onPress={() => push('Other')} title="Push another screen" />
<Button
onPress={() => push('ScreenWithNoHeader')}
title="Push screen with no header"
/>
<Button onPress={() => navigation.goBack(null)} title="Go Home" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
class OtherScreen extends React.Component<NavScreenProps> {
static navigationOptions = {
title: 'Your title here',
};
render() {
const { navigation } = this.props;
const { push, pop } = navigation;
invariant(push && pop, 'missing action creators for StackNavigator');
return (
<SafeAreaView style={{ paddingTop: 30 }}>
<Button
onPress={() => push('ScreenWithLongTitle')}
title="Push another screen"
/>
<Button
onPress={() => push('ScreenWithNoHeader')}
title="Push screen with no header"
/>
<Button onPress={() => pop()} title="Pop" />
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
class ScreenWithLongTitle extends React.Component<NavScreenProps> {
static navigationOptions = {
title: "Another title that's kind of long",
};
render() {
const { navigation } = this.props;
const { pop } = navigation;
invariant(pop, 'missing `pop` action creator for StackNavigator');
return (
<SafeAreaView style={{ paddingTop: 30 }}>
<Button onPress={() => pop()} title="Pop" />
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
class ScreenWithNoHeader extends React.Component<NavScreenProps> {
static navigationOptions = {
header: null,
title: 'No Header',
};
render() {
const { navigation } = this.props;
const { push, pop } = navigation;
invariant(push && pop, 'missing action creators for StackNavigator');
return (
<SafeAreaView style={{ paddingTop: 30 }}>
<Button onPress={() => push('Other')} title="Push another screen" />
<Button onPress={() => pop()} title="Pop" />
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
const StackWithHeaderPreset = createStackNavigator(
{
Home: HomeScreen,
Other: OtherScreen,
ScreenWithNoHeader: ScreenWithNoHeader,
ScreenWithLongTitle: ScreenWithLongTitle,
},
{
headerTransitionPreset: 'uikit',
}
);
export default StackWithHeaderPreset;

View File

@@ -0,0 +1,249 @@
/**
* @flow
*/
import type {
NavigationScreenProp,
NavigationEventSubscription,
} from 'react-navigation';
import { isIphoneX } from 'react-native-iphone-x-helper';
import * as React from 'react';
import { BlurView, Constants } from 'expo';
import {
Dimensions,
Platform,
ScrollView,
StatusBar,
StyleSheet,
View,
} from 'react-native';
import { Header, createStackNavigator } from 'react-navigation';
import invariant from 'invariant';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
import { HeaderButtons } from './commonComponents/HeaderButtons';
type MyNavScreenProps = {
navigation: NavigationScreenProp<*>,
banner: React.Node,
};
class MyNavScreen extends React.Component<MyNavScreenProps> {
render() {
const { navigation, banner } = this.props;
const { push, replace, popToTop, pop } = navigation;
invariant(
push && replace && popToTop && pop,
'missing action creators for StackNavigator'
);
return (
<ScrollView style={{ flex: 1 }} {...this.getHeaderInset()}>
<SampleText>{banner}</SampleText>
<Button
onPress={() => push('Profile', { name: 'Jane' })}
title="Push a profile screen"
/>
<Button
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
title="Navigate to a photos screen"
/>
<Button
onPress={() => replace('Profile', { name: 'Lucy' })}
title="Replace with profile"
/>
<Button onPress={() => popToTop()} title="Pop to top" />
<Button onPress={() => pop()} title="Pop" />
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</ScrollView>
);
}
// Inset to compensate for navigation bar being transparent.
// And improved abstraction for this will be built in to react-navigation
// at some point.
getHeaderInset() {
const NOTCH_HEIGHT = isIphoneX() ? 25 : 0;
// $FlowIgnore: we will remove the HEIGHT static soon enough
const BASE_HEADER_HEIGHT = Header.HEIGHT;
const HEADER_HEIGHT =
Platform.OS === 'ios'
? BASE_HEADER_HEIGHT + NOTCH_HEIGHT
: BASE_HEADER_HEIGHT + Constants.statusBarHeight;
return Platform.select({
ios: {
contentInset: { top: HEADER_HEIGHT },
contentOffset: { y: -HEADER_HEIGHT },
},
android: {
contentContainerStyle: {
paddingTop: HEADER_HEIGHT,
},
},
});
}
}
type MyHomeScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyHomeScreen extends React.Component<MyHomeScreenProps> {
static navigationOptions = {
title: 'Welcome',
};
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onWF);
this._s1 = this.props.navigation.addListener('didFocus', this._onDF);
this._s2 = this.props.navigation.addListener('willBlur', this._onWB);
this._s3 = this.props.navigation.addListener('didBlur', this._onDB);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onWF = a => {
console.log('_willFocus HomeScreen', a);
};
_onDF = a => {
console.log('_didFocus HomeScreen', a);
};
_onWB = a => {
console.log('_willBlur HomeScreen', a);
};
_onDB = a => {
console.log('_didBlur HomeScreen', a);
};
render() {
const { navigation } = this.props;
return <MyNavScreen banner="Home Screen" navigation={navigation} />;
}
}
type MyPhotosScreenProps = {
navigation: NavigationScreenProp<*>,
};
class MyPhotosScreen extends React.Component<MyPhotosScreenProps> {
static navigationOptions = {
title: 'Photos',
};
_s0: NavigationEventSubscription;
_s1: NavigationEventSubscription;
_s2: NavigationEventSubscription;
_s3: NavigationEventSubscription;
componentDidMount() {
this._s0 = this.props.navigation.addListener('willFocus', this._onWF);
this._s1 = this.props.navigation.addListener('didFocus', this._onDF);
this._s2 = this.props.navigation.addListener('willBlur', this._onWB);
this._s3 = this.props.navigation.addListener('didBlur', this._onDB);
}
componentWillUnmount() {
this._s0.remove();
this._s1.remove();
this._s2.remove();
this._s3.remove();
}
_onWF = a => {
console.log('_willFocus PhotosScreen', a);
};
_onDF = a => {
console.log('_didFocus PhotosScreen', a);
};
_onWB = a => {
console.log('_willBlur PhotosScreen', a);
};
_onDB = a => {
console.log('_didBlur PhotosScreen', a);
};
render() {
const { navigation } = this.props;
return (
<MyNavScreen
banner={`${navigation.state.params.name}'s Photos`}
navigation={navigation}
/>
);
}
}
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.mode === 'edit' ? 'Now Editing ' : ''}${
navigation.state.params.name
}'s Profile`}
navigation={navigation}
/>
);
MyProfileScreen.navigationOptions = props => {
const { navigation } = props;
const { state, setParams } = navigation;
const { params } = state;
return {
headerBackImage: params.headerBackImage,
headerTitle: `${params.name}'s Profile!`,
// Render a button on the right side of the header.
// When pressed switches the screen to edit mode.
headerRight: (
<HeaderButtons>
<HeaderButtons.Item
title={params.mode === 'edit' ? 'Done' : 'Edit'}
onPress={() =>
setParams({ mode: params.mode === 'edit' ? '' : 'edit' })
}
/>
</HeaderButtons>
),
};
};
const StackWithTranslucentHeader = createStackNavigator(
{
Home: {
screen: MyHomeScreen,
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
Photos: {
path: 'photos/:name',
screen: MyPhotosScreen,
},
},
{
headerTransitionPreset: 'uikit',
navigationOptions: {
headerTransparent: true,
headerStyle: {
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#A7A7AA',
},
headerBackground: Platform.select({
ios: <BlurView style={{ flex: 1 }} intensity={98} />,
android: (
<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.7)' }} />
),
}),
},
}
);
export default StackWithTranslucentHeader;

View File

@@ -3,11 +3,16 @@
*/
import React from 'react';
import { Button, ScrollView, StatusBar } from 'react-native';
import { SafeAreaView, StackNavigator, TabNavigator } from 'react-navigation';
import { ScrollView, StatusBar } from 'react-native';
import {
SafeAreaView,
createStackNavigator,
createBottomTabNavigator,
} from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
@@ -51,7 +56,7 @@ const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const MainTab = StackNavigator({
const MainTab = createStackNavigator({
Home: {
screen: MyHomeScreen,
path: '/',
@@ -68,7 +73,7 @@ const MainTab = StackNavigator({
},
});
const SettingsTab = StackNavigator({
const SettingsTab = createStackNavigator({
Settings: {
screen: MySettingsScreen,
path: '/',
@@ -84,7 +89,7 @@ const SettingsTab = StackNavigator({
},
});
const StacksInTabs = TabNavigator(
const StacksInTabs = createBottomTabNavigator(
{
MainTab: {
screen: MainTab,
@@ -116,9 +121,9 @@ const StacksInTabs = TabNavigator(
},
},
{
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
tabBarOptions: {
showLabel: false,
},
}
);

View File

@@ -3,11 +3,16 @@
*/
import React from 'react';
import { Button, ScrollView, StatusBar } from 'react-native';
import { SafeAreaView, StackNavigator, TabNavigator } from 'react-navigation';
import { ScrollView, StatusBar } from 'react-native';
import {
SafeAreaView,
createStackNavigator,
createBottomTabNavigator,
} from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
@@ -50,7 +55,7 @@ const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const TabNav = TabNavigator(
const TabNav = createBottomTabNavigator(
{
MainTab: {
screen: MyHomeScreen,
@@ -89,7 +94,20 @@ const TabNav = TabNavigator(
}
);
const StacksOverTabs = StackNavigator({
TabNav.navigationOptions = ({ navigation }) => {
let { routeName } = navigation.state.routes[navigation.state.index];
let title;
if (routeName === 'SettingsTab') {
title = 'Settings';
} else if (routeName === 'MainTab') {
title = 'Home';
}
return {
title,
};
};
const StacksOverTabs = createStackNavigator({
Root: {
screen: TabNav,
},
@@ -102,9 +120,9 @@ const StacksOverTabs = StackNavigator({
Profile: {
screen: MyProfileScreen,
path: '/people/:name',
navigationOptions: ({ navigation }) => {
title: `${navigation.state.params.name}'s Profile!`;
},
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile!`,
}),
},
});

View File

@@ -0,0 +1,142 @@
/**
* @flow
*/
import React from 'react';
import { View, ScrollView, StatusBar, StyleSheet } from 'react-native';
import {
SafeAreaView,
createStackNavigator,
createMaterialTopTabNavigator,
} from 'react-navigation';
import { Constants } from 'expo';
import { MaterialTopTabBar } from 'react-navigation-tabs';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const HEADER_HEIGHT = 64;
const MyNavScreen = ({ navigation, banner, statusBarStyle }) => (
<ScrollView>
<SafeAreaView forceInset={{ horizontal: 'always' }}>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jordan' })}
title="Open profile screen"
/>
<Button
onPress={() => navigation.navigate('NotifSettings')}
title="Open notifications screen"
/>
<Button
onPress={() => navigation.navigate('SettingsTab')}
title="Go to settings tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
<StatusBar barStyle={statusBarStyle || 'default'} />
</ScrollView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen
banner="Home Screen"
navigation={navigation}
statusBarStyle="light-content"
/>
);
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.name}s Profile`}
navigation={navigation}
/>
);
const MyNotificationsSettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen
banner="Settings Screen"
navigation={navigation}
statusBarStyle="light-content"
/>
);
const styles = StyleSheet.create({
stackHeader: {
height: HEADER_HEIGHT,
},
tab: {
height: HEADER_HEIGHT,
},
});
function MaterialTopTabBarWithStatusBar(props) {
return (
<View
style={{
paddingTop: Constants.statusBarHeight,
backgroundColor: '#2196f3',
}}
>
<MaterialTopTabBar {...props} jumpToIndex={() => {}} />
</View>
);
}
const TabNavigator = createMaterialTopTabNavigator(
{
MainTab: {
screen: MyHomeScreen,
navigationOptions: {
title: 'Welcome',
},
},
SettingsTab: {
screen: MySettingsScreen,
navigationOptions: {
title: 'Settings',
},
},
},
{
tabBarComponent: MaterialTopTabBarWithStatusBar,
tabBarOptions: {
tabStyle: styles.tab,
},
}
);
const StackNavigator = createStackNavigator(
{
Root: {
screen: TabNavigator,
navigationOptions: {
header: null,
},
},
NotifSettings: {
screen: MyNotificationsSettingsScreen,
navigationOptions: {
title: 'Notifications',
},
},
Profile: {
screen: MyProfileScreen,
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile!`,
}),
},
},
{
navigationOptions: {
headerStyle: styles.stackHeader,
},
}
);
export default StackNavigator;

View File

@@ -0,0 +1,102 @@
import React from 'react';
import { StatusBar, Text, View } from 'react-native';
import { createStackNavigator } from 'react-navigation';
import { Button } from './commonComponents/ButtonWithMargin';
class HomeScreen extends React.Component<any, any> {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home</Text>
<Button
title="Navigate to 'Profile' with key 'A'"
onPress={() =>
this.props.navigation.navigate({
routeName: 'Profile',
key: 'A',
params: { homeKey: this.props.navigation.state.key },
})
}
/>
<Button
title="Go back to other examples"
onPress={() => this.props.navigation.goBack(null)}
/>
<StatusBar barStyle="default" />
</View>
);
}
}
class ProfileScreen extends React.Component<any, any> {
render() {
const { homeKey } = this.props.navigation.state.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile</Text>
<Button
title="Navigate to 'Settings' with key 'B'"
onPress={() =>
this.props.navigation.navigate({
routeName: 'Settings',
key: 'B',
params: { homeKey },
})
}
/>
<Button
title={`Navigate back to 'Home' with key ${homeKey}`}
onPress={() =>
this.props.navigation.navigate({ routeName: 'Home', key: homeKey })
}
/>
</View>
);
}
}
class SettingsScreen extends React.Component<any, any> {
render() {
const { homeKey } = this.props.navigation.state.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Settings</Text>
<Button
title={`Navigate back to 'Home' with key ${homeKey}`}
onPress={() =>
this.props.navigation.navigate({ routeName: 'Home', key: homeKey })
}
/>
<Button
title="Navigate back to 'Profile' with key 'A'"
onPress={() =>
this.props.navigation.navigate({
routeName: 'Profile',
key: 'A',
})
}
/>
</View>
);
}
}
const Stack = createStackNavigator(
{
Home: {
screen: HomeScreen,
},
Profile: {
screen: ProfileScreen,
},
Settings: {
screen: SettingsScreen,
},
},
{
headerMode: 'none',
}
);
export default Stack;

View File

@@ -0,0 +1,121 @@
/**
* @flow
*/
import React from 'react';
import {
ActivityIndicator,
AsyncStorage,
StatusBar,
StyleSheet,
View,
} from 'react-native';
import { createStackNavigator, createSwitchNavigator } from 'react-navigation';
import { Button } from './commonComponents/ButtonWithMargin';
class SignInScreen extends React.Component<any, any> {
static navigationOptions = {
title: 'Please sign in',
};
render() {
return (
<View style={styles.container}>
<Button title="Sign in!" onPress={this._signInAsync} />
<Button
title="Go back to other examples"
onPress={() => this.props.navigation.goBack(null)}
/>
<StatusBar barStyle="default" />
</View>
);
}
_signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('Home');
};
}
class HomeScreen extends React.Component<any, any> {
static navigationOptions = {
title: 'Welcome to the app!',
};
render() {
return (
<View style={styles.container}>
<Button title="Show me more of the app" onPress={this._showMoreApp} />
<Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
<StatusBar barStyle="default" />
</View>
);
}
_showMoreApp = () => {
this.props.navigation.navigate('Other');
};
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class OtherScreen extends React.Component<any, any> {
static navigationOptions = {
title: 'Lots of features here',
};
render() {
return (
<View style={styles.container}>
<Button title="I'm done, sign me out" onPress={this._signOutAsync} />
<StatusBar barStyle="default" />
</View>
);
}
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class LoadingScreen extends React.Component<any, any> {
componentDidMount() {
this._bootstrapAsync();
}
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
let initialRouteName = userToken ? 'App' : 'Auth';
this.props.navigation.navigate(initialRouteName);
};
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = createStackNavigator({ SignIn: SignInScreen });
export default createSwitchNavigator({
Loading: LoadingScreen,
App: AppStack,
Auth: AuthStack,
});

View File

@@ -1,127 +0,0 @@
/**
* @flow
*/
import React from 'react';
import { Animated, Button, ScrollView, StatusBar } from 'react-native';
import { StackNavigator, TabNavigator } from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import SampleText from './SampleText';
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jordan' })}
title="Open profile screen"
/>
<Button
onPress={() => navigation.navigate('NotifSettings')}
title="Open notifications screen"
/>
<Button
onPress={() => navigation.navigate('SettingsTab')}
title="Go to settings tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
<StatusBar barStyle="default" />
</ScrollView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen banner="Home Screen" navigation={navigation} />
);
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.name}s Profile`}
navigation={navigation}
/>
);
const MyNotificationsSettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const MainTab = StackNavigator({
Home: {
screen: MyHomeScreen,
path: '/',
navigationOptions: {
title: 'Welcome',
},
},
Profile: {
screen: MyProfileScreen,
path: '/people/:name',
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile!`,
}),
},
});
const SettingsTab = StackNavigator({
Settings: {
screen: MySettingsScreen,
path: '/',
navigationOptions: () => ({
title: 'Settings',
}),
},
NotifSettings: {
screen: MyNotificationsSettingsScreen,
navigationOptions: {
title: 'Notifications',
},
},
});
const TabAnimations = TabNavigator(
{
MainTab: {
screen: MainTab,
path: '/',
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
SettingsTab: {
screen: SettingsTab,
path: '/settings',
navigationOptions: {
tabBarLabel: 'Settings',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-settings' : 'ios-settings-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
},
{
tabBarPosition: 'bottom',
animationEnabled: true,
configureTransition: (currentTransitionProps,nextTransitionProps) => ({
timing: Animated.spring,
tension: 1,
friction: 35,
}),
swipeEnabled: false,
}
);
export default TabAnimations;

View File

@@ -3,13 +3,13 @@
*/
import React from 'react';
import { Button, Platform, ScrollView } from 'react-native';
import { TabNavigator, DrawerNavigator } from 'react-navigation';
import { Platform, ScrollView } from 'react-native';
import { createDrawerNavigator } from 'react-navigation';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import SimpleTabs from './SimpleTabs';
import StacksOverTabs from './StacksOverTabs';
const TabsInDrawer = DrawerNavigator({
const TabsInDrawer = createDrawerNavigator({
SimpleTabs: {
screen: SimpleTabs,
navigationOptions: {

View File

@@ -0,0 +1,127 @@
/**
* @flow
*/
import React from 'react';
import { FlatList, SafeAreaView, StatusBar, Text, View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const Event = ({ event }) => (
<View
style={{
borderColor: 'grey',
borderWidth: 1,
borderRadius: 3,
padding: 5,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Text>{event.type}</Text>
<Text>
{event.action.type.replace('Navigation/', '')}
{event.action.routeName ? '=>' + event.action.routeName : ''}
</Text>
</View>
);
const createTabScreen = (name, icon, focusedIcon) => {
class TabScreen extends React.Component<any, any> {
static navigationOptions = {
tabBarLabel: name,
tabBarIcon: ({ tintColor, focused }) => (
<MaterialCommunityIcons
name={focused ? focusedIcon : icon}
size={26}
style={{ color: focused ? tintColor : '#ccc' }}
/>
),
};
state = { eventLog: [] };
append = navigationEvent => {
this.setState(({ eventLog }) => ({
eventLog: eventLog.concat(navigationEvent),
}));
};
render() {
return (
<SafeAreaView
forceInset={{ horizontal: 'always', top: 'always' }}
style={{
flex: 1,
}}
>
<Text
style={{
margin: 10,
marginTop: 30,
fontSize: 30,
fontWeight: 'bold',
}}
>
Events for tab {name}
</Text>
<View style={{ flex: 1, width: '100%', marginTop: 10 }}>
<FlatList
data={this.state.eventLog}
keyExtractor={item => `${this.state.eventLog.indexOf(item)}`}
renderItem={({ item }) => (
<View
style={{
marginVertical: 5,
marginHorizontal: 10,
backgroundColor: '#e4e4e4',
}}
>
<Event event={item} />
</View>
)}
/>
</View>
<NavigationEvents
onWillFocus={this.append}
onDidFocus={this.append}
onWillBlur={this.append}
onDidBlur={this.append}
/>
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
return TabScreen;
};
const TabsWithNavigationEvents = createMaterialBottomTabNavigator(
{
One: {
screen: createTabScreen('One', 'numeric-1-box-outline', 'numeric-1-box'),
},
Two: {
screen: createTabScreen('Two', 'numeric-2-box-outline', 'numeric-2-box'),
},
Three: {
screen: createTabScreen(
'Three',
'numeric-3-box-outline',
'numeric-3-box'
),
},
},
{
shifting: false,
activeTintColor: '#F44336',
}
);
export default TabsWithNavigationEvents;

View File

@@ -0,0 +1,103 @@
/**
* @flow
*/
import React from 'react';
import { SafeAreaView, StatusBar, Text, View } from 'react-native';
import { withNavigationFocus } from 'react-navigation';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { Button } from './commonComponents/ButtonWithMargin';
import SampleText from './SampleText';
class Child extends React.Component<any, any> {
render() {
return (
<Text style={{ color: this.props.isFocused ? 'green' : 'maroon' }}>
{this.props.isFocused
? 'I know that my parent is focused!'
: 'My parent is not focused! :O'}
</Text>
);
}
}
const ChildWithNavigationFocus = withNavigationFocus(Child);
const createTabScreen = (name, icon, focusedIcon, tintColor = '#673ab7') => {
class TabScreen extends React.Component<any, any> {
static navigationOptions = {
tabBarLabel: name,
tabBarIcon: ({ tintColor, focused }) => (
<MaterialCommunityIcons
name={focused ? focusedIcon : icon}
size={26}
style={{ color: focused ? tintColor : '#ccc' }}
/>
),
};
state = { showChild: false };
render() {
const { isFocused } = this.props;
return (
<SafeAreaView
forceInset={{ horizontal: 'always', top: 'always' }}
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ fontWeight: '700', fontSize: 16, marginBottom: 5 }}>
{'Tab ' + name.toLowerCase()}
</Text>
<Text style={{ marginBottom: 20 }}>
{'props.isFocused: ' + (isFocused ? ' true' : 'false')}
</Text>
{this.state.showChild ? (
<ChildWithNavigationFocus />
) : (
<Button
title="Press me"
onPress={() => this.setState({ showChild: true })}
/>
)}
<Button
onPress={() => this.props.navigation.pop()}
title="Back to other examples"
/>
<StatusBar barStyle="default" />
</SafeAreaView>
);
}
}
return withNavigationFocus(TabScreen);
};
const TabsWithNavigationFocus = createMaterialBottomTabNavigator(
{
One: {
screen: createTabScreen('One', 'numeric-1-box-outline', 'numeric-1-box'),
},
Two: {
screen: createTabScreen('Two', 'numeric-2-box-outline', 'numeric-2-box'),
},
Three: {
screen: createTabScreen(
'Three',
'numeric-3-box-outline',
'numeric-3-box'
),
},
},
{
shifting: false,
activeTintColor: '#F44336',
}
);
export default TabsWithNavigationFocus;

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,18 @@
import { Button as RNButton, StyleSheet, View, Platform } from 'react-native';
import React from 'react';
export const Button = props => (
<View style={styles.margin}>
<RNButton {...props} />
</View>
);
const styles = StyleSheet.create({
margin: {
...Platform.select({
android: {
margin: 10,
},
}),
},
});

View File

@@ -0,0 +1,16 @@
import DefaultHeaderButtons from 'react-navigation-header-buttons';
import * as React from 'react';
import { Platform } from 'react-native';
export class HeaderButtons extends React.PureComponent {
static Item = DefaultHeaderButtons.Item;
render() {
return (
<DefaultHeaderButtons
color={Platform.OS === 'ios' ? '#037aff' : 'black'}
{...this.props}
/>
);
}
}

View File

@@ -2,33 +2,42 @@
"name": "NavigationPlayground",
"version": "0.1.0",
"private": true,
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"main": "node_modules/expo/AppEntry.js",
"private": true,
"scripts": {
"postinstall":
"rm -rf node_modules/react-navigation/{node_modules,examples}",
"start": "react-native-scripts start",
"eject": "react-native-scripts eject",
"android": "react-native-scripts android",
"ios": "react-native-scripts ios",
"test": "node node_modules/jest/bin/jest.js"
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"test": "flow"
},
"dependencies": {
"expo": "^24.0.2",
"react": "16.0.0",
"react-native": "^0.51.0",
"react-navigation": "file:../.."
"expo": "^28.0.0",
"invariant": "^2.2.4",
"react": "16.3.1",
"react-native": "^0.55.0",
"react-native-iphone-x-helper": "^1.0.2",
"react-navigation": "link:../..",
"react-navigation-header-buttons": "^0.0.4",
"react-navigation-material-bottom-tabs": "^0.3.0",
"react-navigation-tabs": "^0.5.1"
},
"devDependencies": {
"babel-jest": "^21.0.0",
"flow-bin": "^0.56.0",
"jest": "^21.0.1",
"jest-expo": "^24.0.0",
"react-native-scripts": "^1.5.0",
"react-test-renderer": "16.0.0"
"babel-jest": "^22.4.1",
"babel-plugin-transform-remove-console": "^6.9.0",
"flow-bin": "^0.67.0",
"jest": "^22.1.3",
"jest-expo": "^28.0.0",
"react-test-renderer": "16.3.1"
},
"jest": {
"preset": "jest-expo",
"moduleFileExtensions": ["web.js", "js", "json", "jsx", "node"],
"moduleFileExtensions": [
"web.js",
"js",
"json",
"jsx",
"node"
],
"modulePathIgnorePatterns": [
"/node_modules/.*/react-native/",
"/node_modules/.*/react/"

View File

@@ -0,0 +1,54 @@
/**
* @noflow
*/
const fs = require('fs');
const path = require('path');
const blacklist = require('metro/src/blacklist');
module.exports = {
getBlacklistRE() {
return blacklist([
/react\-navigation\/examples\/(?!NavigationPlayground).*/,
/react\-navigation\/node_modules\/react-native\/(.*)/,
/react\-navigation\/node_modules\/react\/(.*)/,
/react\-navigation\/node_modules\/react-native-paper\/(.*)/,
/react\-navigation\/node_modules\/@expo\/vector-icons\/(.*)/,
]);
},
extraNodeModules: getNodeModulesForDirectory(path.resolve('.')),
};
function getNodeModulesForDirectory(rootPath) {
const nodeModulePath = path.join(rootPath, 'node_modules');
const folders = fs.readdirSync(nodeModulePath);
return folders.reduce((modules, folderName) => {
const folderPath = path.join(nodeModulePath, folderName);
if (folderName.startsWith('@')) {
const scopedModuleFolders = fs.readdirSync(folderPath);
const scopedModules = scopedModuleFolders.reduce(
(scopedModules, scopedFolderName) => {
scopedModules[
`${folderName}/${scopedFolderName}`
] = maybeResolveSymlink(path.join(folderPath, scopedFolderName));
return scopedModules;
},
{}
);
return Object.assign({}, modules, scopedModules);
}
modules[folderName] = maybeResolveSymlink(folderPath);
return modules;
}, {});
}
function maybeResolveSymlink(maybeSymlinkPath) {
if (fs.lstatSync(maybeSymlinkPath).isSymbolicLink()) {
const resolved = path.resolve(
path.dirname(maybeSymlinkPath),
fs.readlinkSync(maybeSymlinkPath)
);
return resolved;
}
return maybeSymlinkPath;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,4 +2,4 @@
## Usage
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
Please see the [Contributors Guide](https://reactnavigation.org/docs/contributing.html#run-the-example-app) for instructions on running these example apps.

View File

@@ -1,22 +1,18 @@
/**
* @flow
*/
import React from 'react';
import { AppRegistry } from 'react-native';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { createStore, applyMiddleware } from 'redux';
import AppReducer from './src/reducers';
import AppWithNavigationState from './src/navigators/AppNavigator';
import { AppNavigator, middleware } from './src/navigators/AppNavigator';
const store = createStore(AppReducer, applyMiddleware(middleware));
class ReduxExampleApp extends React.Component {
store = createStore(AppReducer);
render() {
return (
<Provider store={this.store}>
<AppWithNavigationState />
<Provider store={store}>
<AppNavigator />
</Provider>
);
}

View File

@@ -2,4 +2,4 @@
## Usage
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
Please see the [Contributors Guide](https://reactnavigation.org/docs/contributing.html#run-the-example-app) for instructions on running these example apps.

View File

@@ -12,13 +12,10 @@
"icon": "./assets/icons/react-navigation.png",
"hideExponentText": false
},
"sdkVersion": "23.0.0",
"sdkVersion": "27.0.0",
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"packagerOpts": {
"assetExts": [
"ttf",
"mp4"
]
"assetExts": ["ttf", "mp4"]
},
"ios": {
"supportsTablet": true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -4,8 +4,6 @@
"private": true,
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"scripts": {
"postinstall":
"rm -rf node_modules/react-navigation/{node_modules,examples}",
"start": "react-native-scripts start",
"eject": "react-native-scripts eject",
"android": "react-native-scripts android",
@@ -23,19 +21,21 @@
]
},
"dependencies": {
"expo": "^23.0.0",
"expo": "^27.0.0",
"prop-types": "^15.5.10",
"react": "16.0.0",
"react-native": "^0.50.3",
"react": "16.3.1",
"react-native": "^0.55.0",
"react-navigation": "link:../..",
"react-navigation-redux-helpers": "^2.0.0-beta.1",
"react-redux": "^5.0.6",
"redux": "^3.7.2"
},
"devDependencies": {
"babel-jest": "^21.0.0",
"jest": "^21.0.1",
"jest-expo": "^23.0.0",
"babel-jest": "^22.4.1",
"flow-bin": "^0.74.0",
"jest": "^22.1.3",
"jest-expo": "^25.1.0",
"react-native-scripts": "^1.3.1",
"react-navigation": "file:../..",
"react-test-renderer": "16.0.0"
}
}

View File

@@ -0,0 +1,52 @@
/**
* @noflow
*/
const fs = require('fs');
const path = require('path');
const blacklist = require('metro/src/blacklist');
module.exports = {
getBlacklistRE() {
return blacklist([
/react\-navigation\/examples\/(?!ReduxExample).*/,
/react\-navigation\/node_modules\/react-native\/(.*)/,
/react\-navigation\/node_modules\/react\/(.*)/
]);
},
extraNodeModules: getNodeModulesForDirectory(path.resolve('.')),
};
function getNodeModulesForDirectory(rootPath) {
const nodeModulePath = path.join(rootPath, 'node_modules');
const folders = fs.readdirSync(nodeModulePath);
return folders.reduce((modules, folderName) => {
const folderPath = path.join(nodeModulePath, folderName);
if (folderName.startsWith('@')) {
const scopedModuleFolders = fs.readdirSync(folderPath);
const scopedModules = scopedModuleFolders.reduce(
(scopedModules, scopedFolderName) => {
scopedModules[
`${folderName}/${scopedFolderName}`
] = maybeResolveSymlink(path.join(folderPath, scopedFolderName));
return scopedModules;
},
{}
);
return Object.assign({}, modules, scopedModules);
}
modules[folderName] = maybeResolveSymlink(folderPath);
return modules;
}, {});
}
function maybeResolveSymlink(maybeSymlinkPath) {
if (fs.lstatSync(maybeSymlinkPath).isSymbolicLink()) {
const resolved = path.resolve(
path.dirname(maybeSymlinkPath),
fs.readlinkSync(maybeSymlinkPath)
);
return resolved;
}
return maybeSymlinkPath;
}

View File

@@ -1,29 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { addNavigationHelpers, StackNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation';
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
} from 'react-navigation-redux-helpers';
import LoginScreen from '../components/LoginScreen';
import MainScreen from '../components/MainScreen';
import ProfileScreen from '../components/ProfileScreen';
export const AppNavigator = StackNavigator({
const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
);
const RootNavigator = createStackNavigator({
Login: { screen: LoginScreen },
Main: { screen: MainScreen },
Profile: { screen: ProfileScreen },
});
const AppWithNavigationState = ({ dispatch, nav }) => (
<AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
);
AppWithNavigationState.propTypes = {
dispatch: PropTypes.func.isRequired,
nav: PropTypes.object.isRequired,
};
const AppWithNavigationState = reduxifyNavigator(RootNavigator, 'root');
const mapStateToProps = state => ({
nav: state.nav,
state: state.nav,
});
export default connect(mapStateToProps)(AppWithNavigationState);
const AppNavigator = connect(mapStateToProps)(AppWithNavigationState);
export { RootNavigator, AppNavigator, middleware };

View File

@@ -1,13 +1,13 @@
import { combineReducers } from 'redux';
import { NavigationActions } from 'react-navigation';
import { AppNavigator } from '../navigators/AppNavigator';
import { RootNavigator } from '../navigators/AppNavigator';
// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = AppNavigator.router.getActionForPathAndParams('Main');
const tempNavState = AppNavigator.router.getStateForAction(firstAction);
const secondAction = AppNavigator.router.getActionForPathAndParams('Login');
const initialNavState = AppNavigator.router.getStateForAction(
const firstAction = RootNavigator.router.getActionForPathAndParams('Main');
const tempNavState = RootNavigator.router.getStateForAction(firstAction);
const secondAction = RootNavigator.router.getActionForPathAndParams('Login');
const initialNavState = RootNavigator.router.getStateForAction(
secondAction,
tempNavState
);
@@ -16,19 +16,19 @@ function nav(state = initialNavState, action) {
let nextState;
switch (action.type) {
case 'Login':
nextState = AppNavigator.router.getStateForAction(
nextState = RootNavigator.router.getStateForAction(
NavigationActions.back(),
state
);
break;
case 'Logout':
nextState = AppNavigator.router.getStateForAction(
nextState = RootNavigator.router.getStateForAction(
NavigationActions.navigate({ routeName: 'Login' }),
state
);
break;
default:
nextState = AppNavigator.router.getStateForAction(action, state);
nextState = RootNavigator.router.getStateForAction(action, state);
break;
}

Some files were not shown because too many files have changed in this diff Show More