【问题标题】:React Native - React Navigation slow transitions when nesting navigatorsReact Native - 嵌套导航器时 React Navigation 过渡缓慢
【发布时间】:2026-01-17 22:05:01
【问题描述】:

我正在使用 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 不会因此受到影响。也许是糟糕的编码或反应导航嵌套问题。

标签: react-native redux react-navigation


【解决方案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】:

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

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

  2. 正如@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吗?