React Native - 嵌套导航器时 React Navigation 过渡缓慢
Posted
技术标签:
【中文标题】React Native - 嵌套导航器时 React Navigation 过渡缓慢【英文标题】:React Native - React Navigation slow transitions when nesting navigators 【发布时间】:2018-02-18 01:05:48 【问题描述】:我正在使用 react-native 构建一个跨平台的原生应用程序,并使用 react-navigation 在屏幕之间导航和使用 redux 管理导航状态。当我嵌套导航器时会出现问题。
例如,我使用 Stack Navigator 作为我的应用程序的默认导航器。
export const DefaultNavigate = new StackNavigator(
Login:
screen: LoginScreen,
,
Home:
screen: AppDrawerNavigate,
,
AppTabNav:
screen: AppTabNavigator,
,
);
我的第一个屏幕是登录屏幕,主屏幕是抽屉导航器。
const AppDrawerNavigate = new DrawerNavigator(
InProcess:
screen: InProcess,
,
Machine:
screen: Machine
,
Settings:
screen: Settings
,
Logout:
screen: Logout
,
ContactUs:
screen: ContactUs
);
当用户在抽屉导航器中单击机器时,我将屏幕导航到在 DefaultNavigator 中声明的 AppTabNav。
const AppTabNavigator = new TabNavigator(
MachineList:
screen: MachineList,
,
CalendarView:
screen: CalendarView,
,
);
这是一个标签导航器,顾名思义有两个屏幕,一个是使用列表视图显示列表,另一个是使用日历视图显示日历。我的 listview 数据源中只有大约 30-40 个项目,因此渲染它们对于 listview 来说是小菜一碟。但是,当从 DrawerNavigator 从任何屏幕导航到机器屏幕时,会有 1-2 秒的延迟,并且 js 线程下降到 -2.1,这确实减慢了转换速度。
如果有人需要抽屉导航器中的机器屏幕代码,那就是这里,
componentDidMount()
if(this.state.loaded)
this.props.navigation.dispatch( type: MACHINE);
render()
return <AppActivityIndicator />
以下是我处理屏幕导航的减速器代码,
case types.MACHINE:
nextState = DefaultNavigate.router.getStateForAction(
NavigationActions.reset(
index: 1,
actions: [
NavigationActions.navigate( routeName: 'Home' ),
NavigationActions.navigate( routeName: 'AppTabNav' )
]
),
state
);
以下是抽屉导航器中MachineList画面的渲染方法,
render()
return (
<View style=styles.container>
<AppStatusBar />
<ListView
initialListSize=10
dataSource=this.state.dataSource
renderRow=this.renderRow.bind(this)
enableEmptySections=true
/>
</View>
);
请帮我解决这个问题。我做错了什么?
依赖项
"dependencies":
"native-base": "^2.3.1",
"react": "16.0.0-alpha.12",
"react-devtools": "^2.5.0",
"react-native": "0.47.1",
"react-native-calendars": "^1.5.8",
"react-native-vector-icons": "^4.3.0",
"react-navigation": "^1.0.0-beta.11",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-persist": "^4.9.1",
"redux-thunk": "^2.2.0"
,
"devDependencies":
"babel-jest": "20.0.3",
"babel-preset-react-native": "3.0.0",
"jest": "20.0.4",
"react-test-renderer": "16.0.0-alpha.12"
,
【问题讨论】:
您找到解决方案了吗? no .. 但是一个变通的工作.. 我使用 componentWillMount 上的超时功能将组件的渲染延迟了 10 毫秒 .. 它仍然显示 JS 线程下降,但 UI 不会因此受到影响。也许是糟糕的编码或反应导航嵌套问题。 【参考方案1】:我遇到了同样的问题。切换屏幕时有相当长的延迟。我发现这个非常有用的博客https://novemberfive.co/blog/react-performance-navigation-animations/
所以问题是
当一个新的屏幕被推送时,React Navigation 会先将它渲染到屏幕外,然后再将它动画到合适的位置。这意味着当一个包含大量组件的复杂屏幕被推送时,很容易需要几百毫秒来渲染
为了解决这个问题,我使用了InteractionManager
。一旦所有动画完成,它基本上会给你回调。
以下是我为避免延迟而采取的措施,修复后应用程序运行良好。希望这会有所帮助。
// @flow
import React, Component from 'react';
import InteractionManager, ActivityIndicator from 'react-native';
class Team extends Component<Props>
state =
isReady : false
componentDidMount()
// 1: Component is mounted off-screen
InteractionManager.runAfterInteractions(() =>
// 2: Component is done animating
// 3: Start fetching the team / or render the view
// this.props.dispatchTeamFetchStart();
this.setState(
isReady: true
)
);
// Render
render()
if(!this.state.isReady)
return <ActivityIndicator />
return(
// Render the complex views
)
...
export default Team;
【讨论】:
我没有办法确认您的答案,但我也认为这会起作用,因为我说过延迟 10 毫秒,然后再推动屏幕修复延迟,所以它也这样做。感谢您的回答。 很棒的解决方案 嘿@Carlos 我应该在每个屏幕上使用InteractionManager.runAfterInteractions(()=>)
,我遇到了过渡缓慢的问题吗?
@OliverD:我会说在您定义了路线的地方使用它。
@Carlos Interest!,我打开了一个问题here,其他人也遇到了同样的问题,也许这是一个错误?【参考方案2】:
我也面临同样的问题。以下步骤帮助我大大减少了延迟时间:
如果您在定义屏幕的地方使用 redux 的 compose
包装了组件(尤其是 BottomTabBar 中的组件),您最好将其删除。这将大大提高过渡的平滑度和速度。
正如@Carlos 上面强调的那样,使用InteractionManager.runAfterInteractions(()=>)
【讨论】:
【参考方案3】:我遇到了同样的问题,对我来说,它有助于使用 NativeStackNavigator 而不是 StackNavigator
【讨论】:
【参考方案4】:我遇到了缓慢的标签导航问题,在我的情况下嵌套东西时会出现缓慢的问题
我有来自 react-navigation/drawer 的抽屉 FIRST LEVEL
第二个,我在抽屉下有来自“@react-navigation/bottom-tabs”的标签SECOND LEVEL
第三件事我有一个堆栈(它有多个屏幕)来自标签下的@react-navigation/stack THIRD LEVEL
<Drawer.Navigator>
<Tab.Navigator>
<Stack.Navigator>
<Stack.Screen name="Home"></Stack.Screen>
<Stack.Screen name="Details"></Stack.Screen>
</Stack.Navigator>
<Stack.Navigator>
<Stack.Screen name="Task"></Stack.Screen>
<Stack.Screen name="Details"></Stack.Screen>
</Stack.Navigator>
.....
</Tab.Navigator>
</Drawer.Navigator>
因此,如果我从上面删除任何东西,那么慢问题就消失了,例如,如果我删除 Drawer.Navigator,那么我只有两个嵌套的东西 Tab.Navigator 和 Stack.Navigator,所以问题就消失了。
所以我做了什么,我删除了 Drawer 并使用原生基础的抽屉(你可以使用另一个抽屉包)。
<Tab.Navigator>
<Stack.Navigator>
<Stack.Screen name="Home"></Stack.Screen>
<Stack.Screen name="Details"></Stack.Screen>
</Stack.Navigator>
<Stack.Navigator>
<Stack.Screen name="Task"></Stack.Screen>
<Stack.Screen name="Details"></Stack.Screen>
</Stack.Navigator>
.....
</Tab.Navigator>
我知道我痛苦了很久,没有找到官方 react-navigation 团队的解决方案,Hope Team 很快就会解决嵌套问题,现在,您可以使用该解决方案。
【讨论】:
【参考方案5】:Optimize memory usage and performance (v5)
对于那些使用第 5 版 React Navigation 的人
您需要先按照react-native-screens 的安装说明进行操作。之后在渲染导航堆栈之前使用以下 sn-p(通常在 index.js 或 App.js 文件中):
// Before rendering any navigation stack
import enableScreens from 'react-native-screens';
enableScreens();
【讨论】:
【参考方案6】:将回调函数传递给预定义的requestAnimationFrame
(无需导入)方法,一旦动画完成,它将自动调用该函数。
requestAnimationFrame(() =>
//enter code here
【讨论】:
【参考方案7】:我也面临堆栈导航器的这个问题,抽屉导航器效果更好.. 在堆栈中,如果包含超过 100 行的内容以及某些导入的组件,它就会开始滞后并在导航时延迟。
我在我的一个堆栈屏幕 InteractionManager 中使用了动画后渲染组件
它有效,但是当我点击返回时,动画快门/滞后
我签出了https://reactnavigation.org/docs/react-native-screens/
正如它所说,react-navigation 已经使用了原生导航组件
用于禁用和使用 RN View:-
import enableScreens from 'react-native-screens'
enableScreens(false)
我禁用了它,现在它的工作方式比原生的好,不知道为什么,目前我处于调试模式,所以不能说这是否是远程视图的原因......
真的很困惑为什么它落后于原生导航而不是在 RN 视图中 谁能让我知道为什么会这样?我想使用原生导航
【讨论】:
对我有用,你试过interactionManager吗?以上是关于React Native - 嵌套导航器时 React Navigation 过渡缓慢的主要内容,如果未能解决你的问题,请参考以下文章
在 React Native 中始终显示底部选项卡导航器 React Navigation 5