React Native栈导航原理与自定义实现问题咨询
React Native 自定义栈导航实现问题解答
虽略感疲惫,但我仍想要实现React Native栈导航功能,以下是我编写的简易演示示例:
import React, { useState } from "react"; const StackScreen = () => { let InitialRoute; let First; let Second; let Third;//assume they are screens of my app. const [stack, setStack] = useState([InitialRoute]); const replace = (screenName: any) => { const tmp: Array<any> = stack.filter((el: any) => el = !screenName); setStack([...stack, screenName]); } const navigate = (screenName: any) => { stack.indexOf(screenName) == -1 ? setStack([...stack, screenName]) : replace(screenName); }//navigate to another screen const goBack = () => { if (stack.length > 1) { const tmp = [...stack]; tmp.pop(); setStack(tmp); } }//they are fuctions. return stack[stack.length - 1]; } const App = () => { return ( <View> <Appbar /> <StackScreen /> <BottomTab or anything i dont want to render while change screens./> </View> ) }
我编写了这个简易演示示例,尽管它和真实场景的实现存在偏差,但我有如下疑问:
- 我从FirstScreen进入SecondScreen,停留一段时间后弹出SecondScreen返回时,我当前编写的代码会重新渲染FirstScreen。请问React Navigation在该场景下会重新渲染对应页面吗?如果答案为否,我要如何实现无重渲染的栈导航逻辑?
- 我当前的这套栈导航实现思路存在哪些问题?
问题解答
1. 页面返回时的重渲染问题
React Navigation 在该场景下不会重新渲染FirstScreen。
React Navigation的栈导航会保留栈内所有已挂载的页面节点,非栈顶的页面只是处于不可见、不可交互的状态,组件本身不会被卸载,内部状态、滚动位置等数据会完整留存,上层页面弹出返回时,下层页面只是重新变为可见状态,不会触发重新挂载或全量重渲染。
要实现无重渲染的栈导航,核心要调整渲染逻辑:
- 不要只渲染栈顶的单个页面组件,遍历栈数组将所有栈内页面全部挂载到组件树中
- 对非栈顶的页面做隐藏处理:可以通过样式设置
opacity: 0、pointerEvents: "none",或者将页面平移到屏幕可视区域外,不要直接将非栈顶页面从组件树移除 - 页面入栈、出栈时给对应页面加过渡动画即可,下层页面因为始终处于挂载状态,返回时自然不会触发重渲染,原有状态也会完整保留。
2. 当前实现的现存问题
这套实现思路离可用的栈导航还有明显差距,主要问题包括:
- 核心方法逻辑错误:
replace方法内的filter判断写的是赋值语句el = !screenName而非相等判断,且filter得到的tmp数组完全没有被使用,本质还是在原栈上追加新页面,根本没有实现替换栈顶的效果 - 导航行为不符合通用预期:常规栈导航执行
navigate跳转到栈内已存在的页面时,会弹出该页面到栈顶之间的所有页面,让目标页面回到栈顶,而不是替换当前栈顶页面 - 页面状态完全丢失:因为只渲染栈顶页面,下层页面会被直接卸载,用户输入的内容、列表滚动位置、组件内部state都会被清空,返回时看到的是完全重置的页面,体验不符合用户预期
- 缺少基础导航能力:没有页面传参、路由参数获取的能力,无法满足页面间数据传递的基础需求
- 缺少页面生命周期感知:没有页面聚焦、失焦的事件回调,页面无法感知自己的激活状态,没法实现聚焦刷新数据、失焦暂停播放等常见逻辑
- 交互体验缺失:页面切换是硬切,没有原生栈导航默认的滑入滑出过渡动画,也没有适配安卓物理返回键、iOS侧滑返回手势
- 导航方法访问不便:没有通过Context将导航方法、路由信息下发到子页面,每个页面要触发导航都需要逐层传递props,嵌套深的页面接入成本极高
- 固定层级组件渲染逻辑缺失:示例中提到的BottomTab这类需要固定在页面下层、不随栈页面切换重渲染的组件,现有逻辑没有做层级处理,很容易出现栈页面覆盖不全、固定组件被遮挡或者层级错误的问题
内容的提问来源于stack exchange,提问作者nayounsang
相关产品推荐
相关产品推荐

