React Native 0.75 -支持布局中的百分比值,新架

2024-08-26  本文已影响0人  涅槃快乐是金

今天,我们很高兴发布 React Native 0.75!

此版本包含多个新功能,如支持 % 值的 Yoga 3.1、新架构的多个稳定性修复,以及建议用户使用 React Native 框架。

主要亮点

1. Yoga 3.1 和布局改进

提示:这些功能仅适用于新架构。如果您希望使用它们,请考虑迁移到新架构。

2. 百分比值在间隙中的应用

function App(): React.JSX.Element {
  return (
    <SafeAreaView
      style={{
        marginTop: 20,
        alignItems: 'center',
        flex: 1,
        rowGap: '20%',
      }}>
      <View
        style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
        <View
          style={{
            backgroundColor: 'purple',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'blue',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'green',
            width: 100,
            height: 100,
          }}
        />
      </View>
      <View
        style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
        <View
          style={{
            backgroundColor: 'lime',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'yellow',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'orange',
            width: 100,
            height: 100,
          }}
        />
      </View>
      <View
        style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
        <View
          style={{
            backgroundColor: 'red',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'violet',
            width: 100,
            height: 100,
          }}
        />
        <View
          style={{
            backgroundColor: 'magenta',
            width: 100,
            height: 100,
          }}
        />
      </View>
    </SafeAreaView>
  );
}

Android:

iOS:

3. 百分比值在变换中的应用

function Translated() {
  return (
    <SafeAreaView
      style={{
        marginTop: 20,
        flex: 1,
        rowGap: '20%',
      }}>
      <View
        style={{
          backgroundColor: 'red',
          width: 100,
          height: 100,
          transform: [{translateY: '100%'}, {translateX: '100%'}],
        }}
      />
    </SafeAreaView>
  );
}

Android:


iOS:

4. 新架构稳定化

5. 访问 jsi::Runtime 的新 API

访问 jsi::Runtime 的示例:

在 iOS 上,您可以使您的 Turbo Native 模块符合 RCTTurboModuleWithJSIBindings 协议。您现在可以实现 installJSIBindingsWithRuntime 方法,这将使您能够线程安全地访问运行时。

@interface RCTSampleTurboModule () <RCTTurboModuleWithJSIBindings>
@end

#pragma mark - RCTTurboModuleWithJSIBindings
- (void)installJSIBindingsWithRuntime:(jsi::Runtime &)runtime {
  runtime.global().setProperty(
    runtime,
    "myGlobalFunction",
    jsi::Function::createFromHostFunction(...));
}

在 Android 上,您可以使您的 Turbo Native 模块符合 TurboModuleWithBindings 接口。您现在可以实现 JNI 方法 getBindingsInstaller,这将使您能够在 C++ 中线程安全地访问运行时。

public class SampleTurboModule extends NativeSampleTurboModuleSpec implements TurboModuleWithJSIBindings

@Override
public native BindingsInstallerHolder getBindingsInstaller();
// C++
jni::local_ref<BindingsInstallerHolder::javaobject> SampleTurboModuleJSIBindings::getBindingsInstaller(jni::alias_ref<jni::object> jobj) {
  return BindingsInstallerHolder::newObjectCxxArgs(
    [](jsi::Runtime& runtime) {
      runtime.global().setProperty(
        runtime,
        “myGlobalFunction”,
        jsi::Function::createFromHostFunction(...));
    }
  );
}

如果您在 UI 线程上并且需要访问运行时,我们引入了一个新的 API:CallInvoker。它由一个方法 invokeAsync 组成,该方法将在 JS 线程上跳转以安全地使用 JS 运行时执行一些工作。这些 API 是向前兼容的。

在 iOS 上,我们提供了 RCTCallInvokerModule 协议。符合此协议后,我们的基础设施将为模块装饰 CallInvoker 的访问。

@interface RCTSampleTurboModule() <RCTCallInvokerModule>

[self.callInvoker callInvoker].invokeAsync([&](jsi::Runtime& runtime) {
  // 在 JS 线程上执行操作
});

在 Android 上,CallInvoker 通过 ReactContext 在名为 CallInvokerHolder 的 JNI 包装器中访问,您可以在跨过 JNI 边界后调用 invokeAsync

// Java
public abstract CallInvokerHolder getJSCallInvokerHolder();
// C++
jsCallInvokerHolder->cthis()->getCallInvoker()->invokeAsync([&](jsi::Runtime& rt) {
  // 在 JS 线程上执行操作
});

这个版本通过引入这些改进和功能,使 React Native 更加灵活和强大,进一步提高了开发效率。

使用框架

正如我们在今年早些时候的 React Conf 上分享的那样,构建 React Native 应用程序的推荐方式现在是通过框架,比如 Expo。

您可以在我们之前的博客文章中了解更多关于此建议的信息:《使用框架构建 React Native 应用程序》。

我们希望为新的 React Native 用户创造成功的基础。我们相信,使用框架可以让您尽可能高效,并在构建新应用程序时为您提供最佳的开发者体验。

为了反映这些建议,此版本包含以下更改:

如果您已经在使用像 Expo 这样的框架,这些更改不会对您产生任何影响。您可以在 Expo SDK 51 中与 React Native 0.75 一起使用(您可以在这个专门的 Expo 文章中找到如何操作的说明)。

如果您没有使用框架或正在构建自己的框架,以下是这些更改将如何影响您的情况。

将模板移至 react-native-community/template

历史上,react-native 曾在 NPM 包内附带一个 /template 文件夹,供社区 CLI 用来创建新项目。这使得模板更新变得相对缓慢,因为每次模板更改都需要新的 React Native 版本。

随着我们最新推荐的使用框架的方式,我们认为在核心 NPM 包内提供一个带有强烈意见的模板与我们的愿景不符。

因此,我们决定将模板移至 @react-native-community/template 包。

这将使社区更容易维护和发展模板,而不必依赖于每次变更都发布一个新的 React Native 版本。此外,这将模板与社区 CLI 联系得更紧密,并使每个人更容易将其作为一个独立的包进行检查和依赖。

对于使用社区 CLI 创建新项目的用户来说,这一变化应该是完全透明的。从现在起,与模板相关的新问题应在模板问题跟踪器上报告。所有依赖模板的工具,例如 upgrade-helper,也已经进行了相应的更新并将继续正常工作。

停止使用 react-native init

与模板类似,为了与新的推荐方法保持一致,react-native init 命令也进行了相应的调整。

历史上,react-native init 是创建新 React Native 项目的默认命令。然而,到 2024 年,我们认为此命令不再提供与框架相同的入门体验。因此,我们不再推荐使用它,取而代之的是您应该使用像 Expo 这样的框架。

您仍然可以使用 react-native init 创建新项目并使用社区 CLI 和模板,但您会看到以下警告:

Init Deprecation

从 2024 年 12 月 31 日起,init 命令将不再创建项目。您将需要选择:

请注意,react-native config 和其他所有命令(除 init 外)将继续正常工作。

信息
为了提供更平滑的迁移体验,react-native@0.75.0 包仍依赖于 @react-native-community/cli,但我们计划在不久的将来移除此依赖项。

自动链接性能改进

在更新 init 命令的过程中,我们还花了一些时间重写了自动链接逻辑,以提高性能。这使得 Android 和 iOS 的构建速度更快。

在使用 React Native 0.75 时,如果您正在使用 Expo,自动链接步骤在 Android 上的运行速度可能会快约 6.5 倍,在 iOS 上快约 1.5 倍。您可以在此处阅读更多关于这些改进的信息。

重大更改

虽然即将到来的部分看起来很长,但我们预计这些重大更改主要会影响到使用 React Native 进行更高级操作的小部分用户。

为了完整性和参考,我们在这里列出了它们。

  1. Touchable 组件在 TypeScript 中不再能用作泛型表达式中的类型

    • TouchableOpacityTouchableHighlight 组件已转换为函数组件。这意味着它们不能再用作值和类型。因此,例如,以下代码不再有效:
    import {TouchableHighlight} from 'react-native';
    const ref = useRef<TouchableHighlight>();
    //                ^^^ TS2749: TouchableHighlight 指的是一个值,但在这里被用作类型。
    //                            您是否是指 `typeof TouchableHighlight`?
    
    • 相反,您应该使用内置的 React 类型 React.ElementRefView 类型:
    import {TouchableHighlight} from 'react-native';
    const ref1 =
      useRef<React.ElementRef<typeof TouchableHighlight>>(); 
    // 或
    const ref2 = useRef<View>();
    
  2. 最后支持 minSdk 23minIOSVersion 13.4 的版本

    • 这些并不是 0.75 版本本身的重大更改,但我们希望告知您,React Native 0.75 将是最后一个支持 minSdk 23(Android 6.0)和 minIOSVersion 13.4 的版本。
    • 从 React Native 0.76 开始,minSdk 版本将是 24(Android 7.0),minIOSVersion 将是 15.1。

    您可以在我们针对 Android 和 iOS 的官方公告中阅读更多内容。

  3. 删除 Android 的 JSIModule

    • com.facebook.react.bridge.JSIModule 是一个 API,我们临时引入了它以便原生模块能够直接在 Android 上访问 JSI。该 API 的访问器在 0.74 中已被弃用,我们验证了在开源中没有对该 API 的有意义的使用,因此我们在 0.75 中将其移除。您可以使用 Turbo Native Modules 作为替代方案。
  4. 将 Android 的 PopUp Menu 移至单独的包

    • 在 0.74 版本中,我们将 Android 的 PopUpMenu 移至 @react-native 范围下的单独包。在 0.75 版本中,我们移除了核心中仍存在的剩余方法:
    UIManagerModule.showPopupMenu()
    UIManagerModule.dismissPopupMenu()
    
    • 作为替代方案,请使用位于 @react-native/popup-menu-android 包中的 <PopupMenuAndroid /> 组件。
  5. 完成 iOS PushNotificationIOS 的弃用工作

    • 在 0.74 版本中,我们弃用了 PushNotificationIOS 模块中的一些 API。

    • 在 0.75 版本中,我们删除了这些 API 以迁移离开旧的通知元数据表示。

    • 删除的 API 包括:

      + (void)didReceiveLocalNotification:(UILocalNotification *)notification;
      + (void)didReceiveRemoteNotification:(NSDictionary *)notification;
      
    • 相反,使用 didReceiveNotification:(UNNotification *)notification

  6. 社区 CLI:删除 ram-bundleprofile-hermes 命令

    • 我们想要宣布社区 CLI 中的两个重大移除:ram-bundleprofile-hermes 命令。
    • ram-bundle 命令是在 React Native 0.59 中引入的,用于直接在内存中加载运行包。此功能现在由我们的默认 JS 引擎 Hermes 取代。您不应再使用 ram-bundle 命令。
    • profile-hermes 命令是一个帮助您分析 JavaScript 代码 CPU 性能的工具。它使用的是旧的 .cpuprofile 格式,最近版本的 Chrome 不再支持该格式。将此功能作为一个独立命令也是我们正在逐步淘汰的,因为我们致力于提高调试工具的质量标准。现在可以通过“Profiler”面板在实验性新调试器中访问 CPU 分析功能(注意:如果从 Chrome 连接到 Hermes,则无法访问此功能)。

其他重大变更

通用

  1. 代码生成:

    • 略微更改了纯 C++ TurboModules 生成的类和结构的名称。我们从名称中删除了 "Cxx" 代号。
    • 由于可能的精度问题,不再支持浮点枚举。
    • 当在 JS 中传递 null 给原生代码中的非可空参数时,现在会抛出错误。
  2. 代码检查:

    • 在进行 ESLint 配置检查时,不再运行 prettier
  3. C++:

    • ScrollViewShadowNode 的构造函数现在需要一个新的布尔参数 includeTransform
    • 移除了 RuntimeExecutor 中的 executeAsynchronouslyexecuteSynchronously_CAN_DEADLOCK
    • JsErrorHandler.h 中将 JsErrorHandlingFunc 重命名为 OnJsError
    • handleFatalError.h 中将 handleJsError 重命名为 OnJsError
    • ReactPrimitives.h 中移除了未使用的导入。
    • LongLivedObjectCollectionLongLivedObjectget 方法现在接受一个 Runtime 参数。
    • utils/jsi.h 文件重命名为 jsi-utils.h
  4. TextInput:

    • 移除了已弃用的 onTextInput 回调。
  5. Pressability:

    • 移除了 onLongPressShouldCancelPress_DEPRECATEDonResponderTerminationRequest_DEPRECATEDonStartShouldSetResponder_DEPRECATED 方法。

Android

  1. ReactViewBackgroundDrawable:

    • 已弃用,改用 CSSBackgroundDrawable。这也移除了 ReactViewBackgroundDrawableColorUtil 中的一些 API。
  2. ReactContext:

    • ReactContextReactApplicationContext 现在是抽象类。请使用 BridgeReactContextBridgelessReactContext
    • 删除了 ReactContext.initializeWithInstance()。请使用 BridgeReactInstance 代替。
    • BridgelessReactContext 中移除了 getJavaScriptContextHolder()。请使用 BridgelessCatalystInstance 代替。
    • 移除了 ReactContext.getRuntimeExecutor()。请使用 BridgelessCatalystInstance
  3. 布局:

    • 支持百分比的 flex gap 值。这些更改影响了一些方法的参数,如 setGapsetRowGapsetColumnGap 的类型从 float 改为 dynamic
    • 在 Android Manifest 中要求支持 RTL(从右到左布局)。
  4. 运行时:

    • ReactHostImpl 中移除了 ReactJsExceptionHandler
    • 当不使用默认模板时,应用程序需要负责返回核心 TurboModules。
  5. 开发支持:

    • 更改了 DevSupportManagerFactory.create(),使其接受一个新的 PausedInDebuggerOverlayManager 参数。
  6. 测量:

    • 删除了 UIManagerModule.measureLayoutRelativeToParent()

iOS

  1. 运行时:

    • 移除了 [RCTHost getSurfacePresenter][RCTHost getModuleRegistry]
    • 移除了 EventPriority 类,并始终使用默认的 EventPriority::AsynchronousBatched。如果构建失败,请删除任何 EventPriority 的使用。
  2. 图像:

    • 移除了未使用的 RCTImageLoadingPerfInstrumentationEnabled
  3. 错误处理:

    • 移除了通过 RCTBridge 访问 RCTRedBox 的能力。
  4. CocoaPods:

    • BUILD_FROM_SOURCE 重命名为 RCT_BUILD_HERMES_FROM_SOURCE
    • React-Codegen 重命名为 ReactCodegen,以便更好地兼容 use_frameworksSwift
  5. TextInput:

    • 移除了已弃用的 onTextInput 回调。

鸣谢

React Native 0.75 包含了 165 位贡献者的超过 1491 次提交。感谢大家的辛勤工作!

特别感谢在此版本发布文档中对功能进行了记录的所有额外作者:

升级至 0.75

请使用 React Native Upgrade Helper 来查看 React Native 版本之间的代码更改,以便为现有项目进行升级,并参考升级文档。

要创建新项目:

npx @react-native-community/cli@latest init MyProject --version latest

如果您使用 Expo,React Native 0.75 将在 Expo SDK 51 中得到支持(有关如何将您的 Expo 项目中的 React Native 更新到 0.75.0 的说明可在专门的文章中找到)。

上一篇 下一篇

猜你喜欢

热点阅读