index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. "use strict";
  2. import {addNavigationHelpers, NavigationActions} from 'react-navigation';
  3. import {createReactNavigationReduxMiddleware, createReduxBoundAddListener} from 'react-navigation-redux-helpers';
  4. import {subReducer, cowValueModel as cow} from 'redux-sac';
  5. import {connect} from 'react-redux';
  6. const {navigate, back, reset} = NavigationActions;
  7. export default navigationStateKey => {
  8. const accessNavigationState = cow(navigationStateKey);
  9. const createNavigationReduxConnector = name => ({
  10. middleware: createReactNavigationReduxMiddleware(name, accessNavigationState),
  11. connectNavigation: connect(
  12. state => ({state: accessNavigationState(state)}),
  13. null,
  14. ({state}, {dispatch}, ownProps) => ({
  15. navigation: addNavigationHelpers({dispatch, state, addListener: createReduxBoundAddListener(name)}),
  16. ...ownProps
  17. })
  18. )
  19. });
  20. const backButtonHandler = ({dispatch, getState}) => {
  21. if (accessNavigationState(getState()).index === 0) return false;
  22. dispatch(back());
  23. return true;
  24. };
  25. const topOfNavigationStack = state => {
  26. const {routes} = accessNavigationState(state);
  27. return routes[routes.length - 1] || {};
  28. };
  29. const createConnectedNavigatorPieces = (BareNavigator, name = "root") => {
  30. const {middleware, connectNavigation} = createNavigationReduxConnector(name);
  31. const bareReducer = (state, action) => BareNavigator.router.getStateForAction(action, state);
  32. return {
  33. Navigator: connectNavigation(BareNavigator),
  34. reducer: subReducer(navigationStateKey, bareReducer),
  35. middleware
  36. };
  37. };
  38. const resetRoutes = routeNames => reset({
  39. actions: routeNames.map(routeName => navigate({routeName})),
  40. index: routeNames.length - 1
  41. });
  42. const isRoute = expected => ({routeName}) => routeName === expected;
  43. const isTopRoute = expected => state => isRoute(expected)(topOfNavigationStack(state));
  44. const goBackFrom = routeName => ({dispatch, getState}) => {
  45. if (isTopRoute(routeName)(getState())) {
  46. dispatch(back());
  47. }
  48. };
  49. const getNavigationState = state => accessNavigationState(state);
  50. return {
  51. backButtonHandler,
  52. api: {
  53. getNavigationState,
  54. topOfNavigationStack,
  55. resetRoutes,
  56. isRoute,
  57. isTopRoute,
  58. goBackFrom
  59. },
  60. createConnectedNavigatorPieces
  61. };
  62. };