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(()=&gt;),我遇到了过渡缓慢的问题吗? @OliverD:我会说在您定义了路线的地方使用它。 @Carlos Interest!,我打开了一个问题here,其他人也遇到了同样的问题,也许这是一个错误?【参考方案2】:

我也面临同样的问题。以下步骤帮助我大大减少了延迟时间:

    如果您在定义屏幕的地方使用 redux 的 compose 包装了组件(尤其是 BottomTabBar 中的组件),您最好将其删除。这将大大提高过渡的平滑度和速度。

    正如@Carlos 上面强调的那样,使用InteractionManager.runAfterInteractions(()=&gt;)

【讨论】:

【参考方案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 Native 中始终显示底部选项卡导航器 React Navigation 5

如何使用嵌套的底部选项卡导航器将导航按钮添加到 React 导航堆栈标题?

React Native刷新屏幕/组件/更改状态

React-Native:导航到堆栈导航器中的抽屉

react-native + react-native-tab-navigator 实现 TabBar