react-native-screens vs react-native-gesture-handler vs react-native-reanimated vs react-navigation vs react-native-navigation
React Native 导航架构与性能基础设施选型指南
react-native-screensreact-native-gesture-handlerreact-native-reanimatedreact-navigationreact-native-navigation類似パッケージ:

React Native 导航架构与性能基础设施选型指南

这五个包分为两类核心功能:导航路由方案(react-navigationreact-native-navigation)与底层性能基础设施(react-native-gesture-handlerreact-native-reanimatedreact-native-screens)。react-navigation 是目前社区最通用的 JavaScript 驱动导航库,而 react-native-navigation 则是基于原生导航控制器的解决方案。其余三个库通常作为基础设施配合导航库使用,分别负责原生手势处理、UI 线程动画渲染和原生屏幕容器管理,旨在解决 React Native 默认桥接模式带来的性能瓶颈。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react-native-screens3,181,2563,6272.58 MB20221日前MIT
react-native-gesture-handler2,924,8726,7013.29 MB943ヶ月前MIT
react-native-reanimated2,810,66110,7163.91 MB3521ヶ月前MIT
react-navigation59,76124,417698 B8952年前MIT
react-native-navigation24,42413,1746.67 MB2371日前MIT

React Native 导航架构与性能基础设施深度对比

在构建高质量的 React Native 应用时,导航和动画性能是决定用户体验的关键。开发者常在这五个包之间感到困惑:哪些是导航器?哪些是底层优化?它们如何协同工作?本文将深入剖析它们的技术架构、适用场景及集成方式。

🗂️ 核心定位:导航路由器 vs 底层基础设施

这五个包并非同一维度的竞争对手,而是分层协作的关系。

导航层负责页面跳转、堆栈管理和状态保持:

  • react-navigation:基于 JavaScript 的路由管理器,灵活且生态丰富。
  • react-native-navigation:基于原生导航控制器的路由方案,性能更强但配置复杂。

基础设施层负责解决 React Native 默认架构的性能瓶颈:

  • react-native-gesture-handler:提供原生手势识别能力。
  • react-native-reanimated:提供 UI 线程动画执行能力。
  • react-native-screens:提供原生屏幕容器管理能力。

💡 注意:现代 react-navigation (v6+) 默认推荐配合三个基础设施库使用,以获得接近原生的体验。

🏗️ 导航架构:JavaScript 驱动 vs 原生控制器

react-navigation 将导航状态保存在 JavaScript 中。

  • 屏幕本质上是受控的 React 组件。
  • 切换屏幕时,通过 JS 状态变化触发渲染。
  • 优势:配置简单,支持动态路由,易于调试。
// react-navigation: 声明式堆栈配置
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

react-native-navigation 将每个屏幕注册为原生控制器。

  • 屏幕切换由原生层直接控制,不经过 JS 桥接。
  • 优势:转场动画更流畅,内存管理更优。
  • 劣势:配置需在原生层注册组件,动态路由较麻烦。
// react-native-navigation: 原生注册与设置根视图
import { Navigation } from 'react-native-navigation';

Navigation.registerComponent('com.example.Home', () => HomeScreen);
Navigation.registerComponent('com.example.Profile', () => ProfileScreen);

Navigation.setRoot({
  root: {
    stack: {
      children: [
        { component: { name: 'com.example.Home' } },
        { component: { name: 'com.example.Profile' } }
      ]
    }
  }
});

🖐️ 手势与动画:UI 线程优先

默认情况下,React Native 的手势和动画运行在 JavaScript 线程。如果 JS 线程繁忙(如大量计算),交互会卡顿。基础设施库解决了这个问题。

react-native-gesture-handler 将手势识别移至原生层。

  • 即使 JS 线程阻塞,滑动返回等手势依然流畅。
  • 必须包裹应用根组件才能生效。
// react-native-gesture-handler: 根视图包裹
import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* 其他组件 */}
    </GestureHandlerRootView>
  );
}

react-native-reanimated 允许动画逻辑在 UI 线程运行。

  • 使用 worklet 将函数序列化并在 UI 线程执行。
  • 适合复杂交互,如跟随手指移动的卡片。
// react-native-reanimated: UI 线程动画
import { useAnimatedStyle, withSpring } from 'react-native-reanimated';

function AnimatedBox() {
  const style = useAnimatedStyle(() => {
    return {
      transform: [{ scale: withSpring(1.2) }]
    };
  });
  return <Animated.View style={style} />;
}

📱 屏幕内存管理:原生容器

react-native-screens 优化了屏幕组件的生命周期。

  • 默认情况下,React Native 所有屏幕都挂载在内存中。
  • 此库将非活跃屏幕卸载或转换为原生片段,显著降低内存占用。
  • 需在应用启动时显式启用。
// react-native-screens: 启用原生屏幕容器
import { enableScreens } from 'react-native-screens';

// 在导入任何导航库之前调用
enableScreens();

⚙️ 集成复杂度与配置对比

特性react-navigationreact-native-navigation基础设施库 (Gesture/Reanimated/Screens)
配置方式JavaScript 声明式原生注册 + JS 配置根组件包裹 + Babel 插件
Expo 支持✅ 完美支持 (托管工作流)⚠️ 需开发工作流 (Dev Client)✅ 完美支持
动态路由✅ 轻松支持❌ 较难 (需预注册)N/A
转场性能🟡 依赖原生栈配置🟢 原生控制器级别🟢 提升手势/动画帧率
社区生态🟢 极大🟡 中等 (Wix 生态)🟢 标准配置

🚧 常见陷阱与注意事项

  1. react-native-gesture-handler 必须包裹最外层 如果忘记使用 GestureHandlerRootView 包裹根组件,手势在特定场景(如模态框内)会失效或延迟。这是新手最常遇到的坑。

  2. react-native-reanimated 需要 Babel 配置 必须添加 react-native-reanimated/plugin 到 Babel 配置文件中,且通常需放在插件列表最后一项,否则 worklet 无法正确转换。

// babel.config.js
module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    'react-native-reanimated/plugin', // 必须放在最后
  ],
};
  1. react-native-navigation 与 Expo 的兼容性 如果你使用 Expo 托管工作流(Managed Workflow),无法直接使用 react-native-navigation,因为它需要原生代码修改。此时 react-navigation 是唯一选择。

💡 最终建议

对于 90% 的新项目: 选择 react-navigation 搭配 react-native-screensreact-native-gesture-handlerreact-native-reanimated

  • 这套组合是目前 React Native 社区的标准最佳实践。
  • 它能提供接近原生的性能,同时保持 JavaScript 的开发效率。
  • Expo 用户可直接使用,无需 eject。

对于特定高性能需求或原生重度依赖项目: 选择 react-native-navigation

  • 适合已有原生团队支持的项目。
  • 适合对导航转场动画有极致要求的应用(如复杂的多层嵌套原生导航)。

总结: 不要将基础设施库视为可选插件。在现代 React Native 开发中,gesture-handlerreanimatedscreens 应被视为核心依赖,无论选择哪种导航方案,它们都是构建流畅用户体验的基石。

選び方: react-native-screens vs react-native-gesture-handler vs react-native-reanimated vs react-navigation vs react-native-navigation

  • react-native-screens:

    对于中大型应用,建议默认启用此库。它将 React 组件包装为原生屏幕容器(如 UINavigationController),显著降低内存占用并提升导航切换性能,通常与 react-navigation 配合使用。

  • react-native-gesture-handler:

    只要你的应用涉及复杂手势(如滑动返回、拖拽排序),必须安装此库。它将手势识别从 JavaScript 线程移至原生层,避免因 JS 阻塞导致的手势延迟,是高性能交互的基础。

  • react-native-reanimated:

    当你需要 60fps 的复杂交互动画(如共享元素转场、物理弹簧效果)时使用。它允许动画逻辑在 UI 线程运行,绕过桥接限制,是实现流畅动画的首选方案。

  • react-navigation:

    如果你的项目基于 Expo 或需要广泛的社区支持,选择 react-navigation。它是目前事实上的标准,配置灵活,支持 JavaScript 风格的声明式路由,适合大多数通用应用场景,且与基础设施库集成度最高。

  • react-native-navigation:

    如果你需要完全原生的导航体验(如复杂的原生转场动画)或正在维护 Wix 生态的老项目,选择 react-native-navigation。它每个屏幕都是独立的原生控制器,性能极佳,但配置偏向原生风格,学习曲线较陡。

react-native-screens のREADME

React Native Screens by Software Mansion

This project aims to expose native navigation container components to React Native. It is not designed to be used as a standalone library but rather as a dependency of a full-featured navigation library.

Fabric

To learn about how to use react-native-screens with Fabric architecture, head over to Fabric README. Instructions on how to run Fabric Example within this repo can be found in the FabricExample README.

Supported platforms

  • iOS
  • Android
  • tvOS
  • visionOS
  • Windows
  • Web

Installation

iOS

Installation on iOS is completely handled with auto-linking, if you have ensured pods are installed after adding this module, no other actions are necessary.

Android

On Android the View state is not persisted consistently across Activity restarts, which can lead to crashes in those cases. It is recommended to override the native Android method called on Activity restarts in your main Activity, to avoid these crashes.

For most people using an app built from the react-native template, that means editing MainActivity.java, likely located in android/app/src/main/java/<your package name>/MainActivity.java

You should add this code, which specifically discards any Activity state persisted during the Activity restart process, to avoid inconsistencies that lead to crashes. Please note that the override code should not be placed inside MainActivityDelegate, but rather directly in MainActivity.

Java
import android.os.Bundle;
import com.swmansion.rnscreens.fragment.restoration.RNScreensFragmentFactory;

public class MainActivity extends ReactActivity {

    //...code

    //react-native-screens override
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getSupportFragmentManager().setFragmentFactory(new RNScreensFragmentFactory());
        super.onCreate(savedInstanceState);
    }

    public static class MainActivityDelegate extends ReactActivityDelegate {
        //...code
    }
}
Kotlin
import android.os.Bundle;
import com.swmansion.rnscreens.fragment.restoration.RNScreensFragmentFactory;

class MainActivity: ReactActivity() {

    //...code

    //react-native-screens override
    override fun onCreate(savedInstanceState: Bundle?) {
      supportFragmentManager.fragmentFactory = RNScreensFragmentFactory()
      super.onCreate(savedInstanceState);
    }
}

For people that must handle cases like this, there is a more detailed discussion of the difficulties in a series of related comments.

Need to use a custom Kotlin version?

Since v3.6.0 react-native-screens has been rewritten with Kotlin. Kotlin version used in this library defaults to 1.4.10.

If you need to use a different Kotlin version, set kotlinVersion ext property in your project's android/build.gradle and the library will use this version accordingly:

buildscript {
    ext {
        ...
        kotlinVersion = "1.4.10"
    }
}

Disclaimer: react-native-screens requires Kotlin 1.3.50 or higher.

Windows

Installation on Windows should be completely handled with auto-linking when using React Native Windows 0.63+. For earlier versions, you must manually link the native module.

How can I take advantage of that?

Screens are already integrated with the React Native's most popular navigation library react-navigation and Expo.

Supported react-native version

Below we present tables with mapping of the library version to the last supported react-native version. These tables are for the 4.x line of the library. For compat tables of 3.x line please see readme on the 3.x branch.

Support for Fabric

Fabric is React Native's default rendering system since 0.76.

Here's a table with summary of supported react-native versions:

library versionreact-native version
4.19.0+0.81.0+
4.14.0+0.79.0+
4.5.0+0.77.0+
4.0.0+0.76.0+

Support for Paper

Paper is the legacy rendering system.

Here's a table with summary of supported react-native versions with old architecture turned on:

library versionreact-native version
4.19.0+0.80.0+
4.14.0+0.79.0+
4.9.0+0.76.0+
4.5.0+0.74.0+
4.0.0+0.72.0+

Usage with react-navigation

[!CAUTION] JS API of the native stack has been moved from react-native-screens/native-stack to @react-navigation/native-stack since version v6. Currently, native stack v5 (imported from react-native-screens/native-stack) is deprecated and will be removed in the upcoming minor release. react-native-screens v4 will support only @react-navigation/native-stack v7.

Screens support is built into react-navigation starting from version 2.14.0 for all the different navigator types (stack, tab, drawer, etc).

To configure react-navigation to use screens instead of plain RN Views for rendering screen views, simply add this library as a dependency to your project:

# bare React Native project
yarn add react-native-screens

# if you use Expo managed workflow
npx expo install react-native-screens

Just make sure that the version of react-navigation you are using is 2.14.0 or higher.

You are all set 🎉 – when screens are enabled in your application code react-navigation will automatically use them instead of relying on plain React Native Views.

Experimental support for react-freeze

You have to use React Native 0.68 or higher, react-navigation 5.x or 6.x and react-native-screens >= v3.9.0

Since v3.9.0, react-native-screens comes with experimental support for react-freeze. It uses the React Suspense mechanism to prevent parts of the React component tree from rendering, while keeping its state untouched.

To benefit from this feature, enable it in your entry file (e.g. App.js) with this snippet:

import { enableFreeze } from 'react-native-screens';

enableFreeze(true);

Want to know more? Check out react-freeze README

Found a bug? File an issue here or directly in react-freeze repository.

Disabling react-native-screens

If, for whatever reason, you'd like to disable native screens support and use plain React Native Views add the following code in your entry file (e.g. App.js):

import { enableScreens } from 'react-native-screens';

enableScreens(false);

You can also disable the usage of native screens per navigator with detachInactiveScreens.

Using createNativeStackNavigator with React Navigation

To take advantage of the native stack navigator primitive for React Navigation that leverages UINavigationController on iOS and Fragment on Android, please refer:

FullWindowOverlay

Native iOS component for rendering views straight under the Window. Based on RCTPerfMonitor. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child View, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/apps/src/tests/Test1096.tsx

Interop with react-native-navigation

React-native-navigation library already uses native containers for rendering navigation scenes so wrapping these scenes with <ScreenContainer> or <Screen> component does not provide any benefits. Yet if you would like to build a component that uses screens primitives under the hood (for example a view pager component) it is safe to use <ScreenContainer> and <Screen> components for that as these work out of the box when rendered on react-native-navigation scenes.

Interop with other libraries

This library should work out of the box with all existing react-native libraries. If you experience problems with interoperability please report an issue.

Guide for navigation library authors

If you are building a navigation library you may want to use react-native-screens to have control over which parts of the React component tree are attached to the native view hierarchy. To do that, react-native-screens provides you with the components documented here.

Common problems

Problems with header on iOS

Solution

Use ScrollView with prop contentInsetAdjustmentBehavior=“automatic” as a main container of the screen and set headerTranslucent: true in screen options.

Other problems

ProblemSolution
SVG component becomes transparent when goBackrelated PRs
Memory leak while moving from one screen to another in the same stackexplanation
LargeHeader stays small after pop/goBack/swipe gesture on iOS 14+potential fix
onScroll and onMomentumScrollEnd of previous screen triggered in bottom tabsexplanation
SplitView doesn't clear the blur under primary column after switching to color with opacity: 0workarounds

Contributing

There are many ways to contribute to this project. See CONTRIBUTING guide for more information. Thank you for your interest in contributing!

License

React native screens library is licensed under The MIT License.

Credits

This project has been build and is maintained thanks to the support from Shopify, Expo.io, and Software Mansion.

shopify expo swm

React Native Screens is created by Software Mansion

Since 2012 Software Mansion is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – Hire us.