blog icon indicating copy to clipboard operation
blog copied to clipboard

react-navigation 集成 redux 后 reducer 写法参考

Open wuweijia opened this issue 7 years ago • 0 comments

/**
 * 导航系统: react-Navigation
 * 参考文档: https://reactnavigation.org/docs/intro/s
 * 拓展: 与redux集成
 */
import { NavigationActions } from 'react-navigation';
import { findIndex, find } from 'lodash';
import AppNavigator, { tabNavigator } from '../router';
// 初始化两个路由待用 一个登陆 一个首页 可以通过用户状态来dispatch选择初始化那个页面
const firstAction = tabNavigator.router.getActionForPathAndParams('ReportHome');
const initialNavState = AppNavigator.router.getStateForAction(
  firstAction
);

const navigation = (state = initialNavState, action) => {
  let nextState;
  let currentTabNav;
  let currentTabNavIndex;
  let changeTabNavIndex;
  let changeTabNav;
  switch (action.type) {
    // 这里用来处理token过期返回到登录页面
    case 'LOGOUT':
      nextState = AppNavigator.router.getStateForAction(
        NavigationActions.reset({
          index: 0,
          actions: [NavigationActions.navigate({ routeName: 'account.guidePage' })],
        })
      );
      break;

    // api
    case 'push':
      if (!action.routeName) {
        throw new Error('缺少routeName');
      }
      nextState = AppNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: action.routeName, params: action.params }),
        state,
      );
      break;
    case 'pop':
      if (state.routes.length === 1) {
        throw new Error('当前路由栈只有一个');
      }
      nextState = {
        ...state,
        index: state.index - 1,
        routes: state.routes.slice(0, state.routes.length - 1),
      };
      break;
    case 'reset':
      nextState = AppNavigator.router.getStateForAction(
        NavigationActions.reset({
          index: action.routes.length - 1,
          actions: action.routes.map(route => (NavigationActions.navigate(
            {
              routeName: route.routeName,
              params: route.params,
            }
          ))),
        })
      );
      // 这里是为了实现跳转到tabnav的某个tab上
      changeTabNav = find(action.routes, { routeName: 'tabNavigator' });
      currentTabNav = find(nextState.routes, { routeName: 'tabNavigator' });
      if (changeTabNav) {
        if (!changeTabNav.tabRouteName) {
          throw new Error('必须指定一个tabRouteName');
        } else {
          if (findIndex(currentTabNav.routes, { routeName: changeTabNav.tabRouteName }) < 0) {
            throw new Error('不存在的tabRouteName');
          }
          currentTabNavIndex = findIndex(nextState.routes, { routeName: 'tabNavigator' });
          changeTabNavIndex = findIndex(nextState.routes[currentTabNavIndex].routes,
           { routeName: changeTabNav.tabRouteName });
          nextState.routes[currentTabNavIndex].index = changeTabNavIndex;
        }
      }
      break;
    case 'replace':
      if (!action.routeName) {
        throw new Error('缺少routeName');
      }
      nextState = {
        ...state,
        index: state.index,
        routes: state.routes
          .slice(0, state.routes.length - 1)
          .concat(AppNavigator.router.getStateForAction(
            NavigationActions.navigate({
              routeName: action.routeName,
              params: action.params,
            })
          ).routes),
      };
      break;
    case 'popToTop':
      nextState = {
        ...state,
        index: 0,
        routes: state.routes.slice(0, 1),
      };
      break;
    case 'popToRoute':
      if (findIndex(state.routes, { routeName: action.routeName }) < 0) {
        throw new Error(`${action.routeName}不在路由栈中`);
      }
      nextState = {
        ...state,
        index: findIndex(state.routes, { routeName: action.routeName }),
        routes: state.routes
          .slice(0, findIndex(state.routes, { routeName: action.routeName }) + 1),
      };
      break;
    default:
      nextState = AppNavigator.router.getStateForAction(action, state);
      break;
  }
  return nextState || state;
};

export default navigation;

wuweijia avatar Nov 29 '17 02:11 wuweijia