首页 > 其他分享 >react-navigation使用redux-saga等处理各种跳转、清除堆栈、返回不同页面的问题

react-navigation使用redux-saga等处理各种跳转、清除堆栈、返回不同页面的问题

时间:2024-08-12 12:49:15浏览次数:9  
标签:const NAME saga ROUTE react state routeName 跳转 routes

react-navigation使用redux-saga等处理各种跳转、清除堆栈、返回不同页面的问题

名字还是土一点好IP属地: 上海 0.272018.01.21 14:26:36字数 154阅读 4,027

一直没有找到有关于 react-navigation 处理app各种不同状态需要默认不同首页的例子,于是只能自己写了。

整个思路大概是这样的: 默认设置一个空页面为root页,根据需求rest至其他页面。

以下完整代码已放在github

实现效果图

  ios效果   ios效果   安卓效果

路由设置

AppNavigation.js

// 用户token有效时默认
export const INITIAL_AUTHEN_ROUTE_NAME = 'Tab'
// 未登录时默认
export const INITIAL_UNAUTHEN_ROUTE_NAME = 'SignIn'
// 引导页首页
export const APPINTRO_ROUTE_NAME = 'AppIntro'
// 其他情况下的首页
...

// 登陆后的路由
const AUTHEN_ROUTES = {
  [INITIAL_AUTHEN_ROUTE_NAME]: { screen: TabNavigation },
  Jump1: { screen: Jump1 },
  Jump2: { screen: Jump2 }
}

export function isAuthenRouteName (routeName) {
  return !!AUTHEN_ROUTES[routeName]
}

// 无需登陆的路由
const UNAUTHEN_ROUTES = {
  SignIn: { screen: SignIn },
  Register: { screen: Register }
}

export function isUnauthenRouteName (routeName) {
  return !!UNAUTHEN_ROUTES[routeName]
}

// 其他特殊情况的路由
const GLOBAL_SCREEN = {
  AppIntro: { screen: AppIntro }
}

// 整个App路由整合
export const AppNavigation = StackNavigator({
  Launcher: { screen: Launcher },
  ...AUTHEN_ROUTES,
  ...UNAUTHEN_ROUTES,
  ...GLOBAL_SCREEN
}, {
  initialRouteName: 'Launcher',
  gesturesEnabled: true,
  headerMode: 'none',
  transitionConfig: () => ({
    screenInterpolator: CardStackStyleInterpolator.forHorizontal
  })
})

处理安卓返回多次问题

AppNavigation.js

const defaultGetStateForAction = AppNavigation.router.getStateForAction
AppNavigation.router.getStateForAction = (action, state) => {
  const { type, routeName } = action

  // jump twice
  if (state &&
    type === NavigationActions.NAVIGATE &&
    routeName === state.routes[state.routes.length - 1].routeName
  ) return null
  
  ...

  return defaultGetStateForAction(action, state)
}

处理返回至某个堆栈

AppNavigation.js

const defaultGetStateForAction = AppNavigation.router.getStateForAction
AppNavigation.router.getStateForAction = (action, state) => {
  const { type, routeName } = action

  ...

  // back to one stack
  if (state && type === NavigationActions.BACK) {
    const backRoute = state.routes.find(route => route.routeName === action.key)
    if (backRoute) {
      const backRouteIndex = state.routes.indexOf(backRoute)
      const route = {
        ...state,
        routes: state.routes.slice(0, backRouteIndex + 1),
        index: backRouteIndex
      }
      return route
    }
  }

  return defaultGetStateForAction(action, state)
}

根据不同状态设置不同根路径

NavigationSagas.js

import { put, select } from 'redux-saga/effects'
import { NavigationActions } from 'react-navigation'

import {
  isAuthenRouteName,
  isUnauthenRouteName,
  INITIAL_AUTHEN_ROUTE_NAME,
  INITIAL_UNAUTHEN_ROUTE_NAME,
  APPINTRO_ROUTE_NAME
} from '../Navigation/AppNavigation'

export function * redirectFlow () {
  const state = yield select()

  const authenticated = state.user.isLoggedIn
  const app = state.app

  const index = state.nav.index
  const routeName = state.nav.routes[index].routeName

  const redirectRoute = (name, childRouteName) => NavigationActions.reset({
    index: 0,
    actions: [
      NavigationActions.navigate({ routeName: name })
    ]
  })
  
  // 需要引导页时
  if (!app.hasReadAppintro) {
    yield put(redirectRoute(APPINTRO_ROUTE_NAME))
  }
  ...
  else {
    // 用户登陆时
    if (authenticated && !isAuthenRouteName(routeName)) {
      yield put(redirectRoute(INITIAL_AUTHEN_ROUTE_NAME))
      
    // 用户未登录时
    } else if (!authenticated && !isUnauthenRouteName(routeName)) {
      yield put(redirectRoute(INITIAL_UNAUTHEN_ROUTE_NAME))
    }
  }
  // 利用启动页遮盖跳转过程
  // SplashScreen.hide()
}

跳转后清除某些堆栈

NavigationSagas.js

// routeName 为要跳转的栈
export function * resetFlow ({ routeName, stackName }) {
  const state = yield select()

  let routes = []

  // 清除 堆栈中 stackName 到 routeName 之间的堆栈
  if (stackName) {
    for (let i = 0; i < state.nav.routes.length; i++) {
      routes.push(state.nav.routes[i])
      if (state.nav.routes[i].routeName === stackName) break
    }
  } else {
    routes = state.nav.routes
  }

  let actions = routes.map((item, key) =>
    key === (routes.length - 1)
    ? NavigationActions.navigate({ routeName: routeName })
    : NavigationActions.navigate({ routeName: item.routeName })
  )

  const redirectRoute = NavigationActions.reset({
    index: actions.length - 1,
    actions: actions
  })

  yield put(redirectRoute)
}

android 返回键处理

RootContainer.js

_BackHandler = () => {
  BackHandler.addEventListener('hardwareBackPress', () => {
    const { routes } = this.props.nav
    if (routes.length > 1) {
      this.props.goBack({ key: routes[routes.length - 1]['key'] })
      return true
    }
    // if in root, < 2s
    if (this.lastBackPressed && (this.lastBackPressed + 2000 >= Date.now())) {
      BackHandler.exitApp()
      return true
    }
    this.lastBackPressed = Date.now()
    Toast.show('again quit')
    return true
  })
}
  最后编辑于 :2018.01.21 14:29:34 ©著作权归作者所有,转载或内容合作请联系作者

标签:const,NAME,saga,ROUTE,react,state,routeName,跳转,routes
From: https://www.cnblogs.com/sexintercourse/p/18354745

相关文章

  • React Router v6 使用指南
    ReactRouterv6使用指南杭州程序员张张 2020-08-19阅读 7 分钟19 本文首发于公众号《前端全栈开发者》,第一时间阅读最新文章,会优先两天发表新文章。关注后私信回复:大礼包,送某网精品视频课程网盘资料,准能为你节省不少钱!在本教程中,让我们看一下......
  • React Router 6 (React路由) 最详细教程
    ReactRouter6(React路由)最详细教程蒋川 2022-03-29阅读 5 分钟3 ReactRouter 经历多个版本的发展,现在已经到了 ReactRouter6。虽然网络上写React-Router路由本身的教程很多,但真正讲到React-Router6的并不多。同时因为第6版引......
  • 07-react应用-组件化编码
    目录样式模块化功能界面的组件化编码流程(通用)案例总结todoList案例相关知识点样式模块化//样式模块化index.module.cssimporthellofrom'./index.module.css'divclassName={hello.title}功能界面的组件化编码流程(通用)拆分组件:拆分界面,抽取组件实......
  • 关于REACT范式的一些思考
    关于REACT范式的一些思考REACT范式经过近一年的探索,让我们在很多领域有了非常广泛的应用,它确实提升了很多之前无法解决的问题,比如大模型虽然在语言理解和交互式决策方面在任务中表现出令人印象深刻的表现,但是如何让模型基于解释来使用LLMs以交错方式生成推理跟踪和特定于任务的......
  • Consider defining a bean of type ‘org.springframework.cloud.client.loadbalancer
    1、bug报错问题:项目启动失败***************************APPLICATIONFAILEDTOSTART***************************Description:Parameter1ofconstructorincom.tianji.learning.controller.InteractionQuestionAdminControllerrequiredabeanoftype'org......
  • 03-react基础-面向组件编程(重要属性-props)
    props属性props的基本使用对props进行限制props简写函数式组件使用propsprops的基本使用作用:通过标签属性从组件外向组件内传递变化的数据<scripttype="text/babel">//创建组件classPersonextendsReact.Component{render(){......
  • react-native 包管理器
    什么是Node.js Node是一个服务端的JavaScript解释器,将改变服务器应该如何工作,Node不是JavaScript而是一个服务器程序 什么是npmnpm(nodepackagemanager)是Node的包管理,允许在Node.js应用中创建、重写、共享 Npm模块的本地安装和全局安装本地安装:安装库在本地项目......
  • pydantic实现LLM ReAct
    在今天的AI项目中,大模型的集成几乎成为了一种常态,但如何在保证输出的可控性和解释性的同时利用这些模型执行各种下游任务,一直是一个技术挑战。本文将介绍一个名为ReAct的系统,该系统通过结合大规模语言模型的输出与Python开发紧密合作,提供了一种新颖的解决方案。代码开源在G......
  • Java中的异步编程模型与事件处理框架:从CompletableFuture到Reactive Streams
    Java中的异步编程模型与事件处理框架:从CompletableFuture到ReactiveStreams大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代软件开发中,异步编程和事件驱动架构变得越来越重要。它们能有效提高应用程序的性能和响应速度,特别是在处理高并发和I......
  • 【笔记摘要】React 框架
     useEffect 将组件连接到外部系统,处理网络、浏览器、DOM、动画、使用不同UI库编写的小部件以及其他非React代码。useInsertionEffect 在React对DOM进行更改之前触发,库可以在此处插入动态CSS默认情况下,当一个组件重新渲染时,React将递归渲染它的所有子组件,但如果你......