React Native 0.74 - Yoga 3.0,无桥新架构等

原文信息: 查看原文查看原文

React Native 0.74 - Yoga 3.0, Bridgeless New Architecture, and more

- Hur Ali、Alan Hughes、Alfonso Curbelo、 Alex Hunt、 Nicola Corti

今天我们发布了 React Native 0.74!此版本增加了 Yoga 3.0,在新架构下默认无桥,批量 onLayout 更新(新架构),以及将 Yarn 3 设置为新项目的默认包管理器。

我们还删除了已弃用的 API,删除了 PropTypes,并对 PushNotificationIOS 进行了破坏性更改。在 Android 上,SDK 23(Android 6.0)现在是支持的最低版本。

亮点

破坏性更改

亮点

Yoga 3.0

新布局行为

React Native 0.74 包含了 Yoga 3.0,我们布局引擎的最新版本。Yoga 3.0 通过使样式更可预测来改进布局,并支持渲染为 Web 编写的组件。

React Native 继续有意地保留一些不正确的布局行为,如果修复这些行为将影响大量真实世界的组件。将来的 React Native 版本中将能够更细粒度地配置布局符合性。

警告

React Native 以前在处理设置在 row-reverse 容器上的 marginpaddingborder 时,会翻转 left/right(以及 start/end)边缘。现在,这些属性的行为与 Web 一致。以前依赖于边缘被反转的代码可能需要更新,以便继续正确渲染。

<View
  style={{
    flexDirection: 'row',
    backgroundColor: 'red',
    margin: 10,
    width: 200,
    height: 100,
  }}>
  <View
    style={{
      flexDirection: 'row-reverse',
      backgroundColor: 'blue',
      flex: 1,
      marginLeft: 50,
    }}>
    <View
      style={{
        backgroundColor: 'green',
        height: '50%',
        flex: 1,
        marginLeft: 50,
      }}
    />
  </View>
</View>

以前的布局

在这一部分中,React Native 0.74引入了一些重要的变化和新功能。让我们来逐一翻译:

新架构:默认启用无桥接模式

在这个版本中,当新架构被启用时,我们将无桥接模式设置为默认。您可以在此帖子中了解更多关于我们将无桥接模式设置为默认的信息。为了使过渡更加顺利,我们增强了Interop层以覆盖无桥接模式,并与几个库合作,确保它们从第一天起就能在无桥接模式下运行。

除了无桥接模式之外,我们还改进了新渲染器Interop层。其中最令人兴奋的部分是现在默认启用了它:您不需要指定必须通过它进行转换的组件!您可以在这里阅读更多关于它们的信息。

最后,如果您想了解更多关于新架构的信息,您可以在react-native-new-architecture存储库中找到文档。当新架构成为默认设置时,这些信息将被整合到reactnative.dev中。

新架构:批处理onLayout更新

在0.74中,onLayout回调中的状态更新现在是批处理的。以前,在onLayout事件中的每个状态更新都会导致一个新的渲染提交。

function MyComponent(props) {
  const [state1, setState1] = useState(false);
  const [state2, setState2] = useState(false);

  return (
    <View>
      <View
        onLayout={() => {
          setState1(true);
       }}>
      <View
         onLayout={() => {
          // 当此事件被执行时,在这里不再观察到state1的新值。
          setState2(true);
        }}>
      </View>
    </View>
  );
}

在0.74中,setState1setState2更新将一起批处理。这种改变是React中预期的行为,并且可以减少重新渲染次数。

危险

此更改可能会破坏代码,因为它依赖于未批处理的状态更新。您需要重构此代码以使用更新程序函数或等效方法。

新项目使用Yarn 3

Yarn 3 现在是使用 React Native Community CLI 初始化的新项目的默认 JavaScript 包管理器。

Yarn 3.x 将与 nodeLinker: node-modules 一起使用,这是一种与 React Native 库兼容的模式。这取代了旧默认值 Yarn Classic (1.x, 已弃用)。要升级现有应用中的 Yarn 版本,您可以按照此指南

$ yarn --help  
━━━ Yarn Package Manager - 3.6.4 ━━━━━━━━━━━━━━━━━━━━━━━━

  $ yarn <command>

Community CLI 还支持通过 --pm 标志用其他包管理器初始化项目(了解更多)。

重大变更

Android最低SDK提升(Android 6.0)

React Native 0.74 的最低 Android SDK 版本要求为 23(Android 6.0)。以前是 Android 5.0(API 21)。有关此更改的上下文,请参见此处

附加信息:Android应用程序大小缩减

最低 SDK 提升,再加上我们在原生构建中的几个改进,使我们能够大大减少用户设备上的应用程序大小。

例如,使用 React Native 0.74 新创建的应用程序在用户设备上占用的空间减少了约 13%,节省了约 4MB 的设备空间。

新创建的 React Native 应用程序在 Android 系统存储视图中的并排比较

删除已弃用的PropTypes

在 0.74 之前,React Native 一直在继续使用已弃用的 PropTypes,这是自 2017 年 React 15.5 弃用以来一直存在的 API!我们现在正在从 React Native 中删除所有内置的 PropTypes,以减少应用程序大小(在最小化的捆绑包中为 26.4kB)和内存开销。

已删除以下 PropTypes 属性:Image.propTypesText.propTypesTextInput.propTypesColorPropTypeEdgeInsetsPropTypePointPropTypeViewPropTypes(请参阅提交)。

如果您的应用程序或库依赖于 PropTypes,我们强烈建议迁移到像 TypeScript 这样的类型系统。

PushNotificationIOS的API更改(已弃用)

在 React Native 0.74 中,我们正在采取措施删除已弃用的 PushNotificationIOS 库。此版本中

的更改重点是删除对旧版 iOS API 的引用。PushNotificationIOS 已迁移到了苹果的 User Notifications 框架,并公开了用于调度和处理通知的新 API。

在下一个版本(0.75)中,我们计划移除此库,并将其从 React Native 核心移出,并放入社区包中,@react-native-community/push-notification-ios。如果您仍在依赖 PushNotificationIOS,请在下一个版本发布之前进行迁移。

API更改

RCTPushNotificationManager 上的 didRegisterUserNotificationSettings: 回调是一个空操作,并已被删除。

RCTPushNotificationManager 上的以下回调已被弃用,并将在 0.75 中删除:

+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;  
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;  

为了使用 getInitialNotification() 检索启动应用程序的通知,现在需要在 RCTPushNotificationManager 上显式设置 initialNotification

[RCTPushNotificationManager setInitialNotification:response.notification];  

在JS端,Notification 上的属性已更改。alertActionrepeatInterval 现已弃用,并将在 0.75 中删除:

type Notification = {  
  ...  // 新:显示通知的时间(从现在起的秒数)。fireIntervalSeconds?: ?number,  
  // 已更改:仅用于调度通知。在使用 `getScheduledLocalNotifications` 或 `getDeliveredNotifications` 检索通知时将为 null。  soundName?: ?string,  
  // 已弃用:这是用于 iOS 的旧 UILocalNotification。  alertAction?: ?string,  
  // 已弃用:请改用 `fireDate` 或 `fireIntervalSeconds`。  repeatInterval?: ?string,};  

最后,PushNotificationIOS.removeEventListener 上的 handler 参数未使用,并已被删除。

💡 迁移方式

iOS

您的 AppDelegate 将需要实现 UNUserNotificationCenterDelegate。这应该在应用程序启动时在 application:willFinishLaunchingWithOptions:application:didFinishLaunchingWithOptions: 中完成(有关更多详细信息,请参见Apple文档)。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
{  
  ...  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];  center.delegate = self;  
  return YES;}  

实现 [userNotificationCenter:willPresentNotification:withCompletionHandler:],当通知到达且应用程序处于 前台 时调用。使用 completionHandler 来确定是否向用户显示通知,并相应地通知 RCTPushNotificationManager

- (void)userNotificationCenter:(UNUserNotificationCenter *)center  
       willPresentNotification:(UNNotification *)notification         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{  
  // 这将触发 PushNotificationIOS 上的 'notification' 和 'localNotification' 事件[RCTPushNotificationManager didReceiveNotification:notification];  // 决定是否以及如何向用户显示通知  completionHandler(UNNotificationPresentationOptionNone);}  

要处理通知被点击时的情况,请实现 [userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:]。请注意,如果在 userNotificationCenter:willPresentNotification:withCompletionHandler: 中将前台通知设置为显示,则应仅在这些回调之一中通知 RCTPushNotificationManager

如果点击的通知导致应用程序启动,请调用 setInitialNotification:。如果通知之前未由 userNotificationCenter:willPresentNotification:withCompletionHandler: 处理,请同时调用 didReceiveNotification:

- (void)  userNotificationCenter:(UNUserNotificationCenter *)center  
  didReceiveNotificationResponse:(UNNotificationResponse *)response           withCompletionHandler:(void (^)(void))completionHandler{  
  // 此条件在通知被点击以启动应用程序时满足  if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {  // 允许在JS端使用 getInitialNotification() 检索通知    [RCTPushNotificationManager setInitialNotification:response.notification];  } // 这将触发 PushNotificationIOS 上的 'notification' 和 'localNotification' 事件[RCTPushNotificationManager didReceiveNotification:response.notification];  completionHandler();}  

最后,删除以下方法,并将逻辑调整为上述回调中的逻辑,这些回调将替代这些方法:

  1. [application:didReceiveLocalNotification:](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622930-application?language=objc) [已弃用]
  2. [application:didReceiveRemoteNotification:](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623117-application?language=objc) [已弃用]
  3. [application:didReceiveRemoteNotification:fetchCompletionHandler:](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application?language=objc) [未弃用,但已被 UNUserNotificationCenterDelegate 方法替代]

还要删除任何使用 [application:didRegisterUserNotificationSettings:](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623022-application?language=objc)RCTPushNotificationManager 相应的 didRegisterUserNotificationSettings: 的用法。

示例:请参阅 RNTester 的 [AppDelegate.mm](https://github.com/facebook/react-native/blob/main/packages/rn-tester/RNTester/AppDelegate.mm)

JS

  1. 删除对 alertAction 的任何引用。
  2. 删除任何调用 removeEventListener 的地方的 handler 参数。
  3. 使用 fireDatefireIntervalSeconds 替换任何对 repeatInterval 的使用,以多次使用 fireDatefireIntervalSeconds 触发通知。
  4. 请注意,在从 getScheduledLocalNotifications()getDeliveredNotifications() 返回的 Notification 上访问 soundName 时,soundName 将为 null。

其他重大变更

通用

  • 使样式中的 start/end 始终指向写入方向(#42251)。

Android

  • FabricUIManagerProvider 中删除 JSIModule*#42059)。
  • 废弃 UIManagerModule.showPopupMenuUIManagerModule.dismissPopupMenu#42441

iOS

  • 从 iOS 代码生成 CLI 中删除 configFilenameconfigKey 参数(#41533)。
  • 更改 bundleURL 的处理方式(#43994)。
    • 以前,当 React Native 在一个实例变量中启动时,bundleURL 被设置,不可能更新它。
    • 现在,bundleUrl 是一个函数,需要在需要时重新评估,从而可以在刷新之间使用不同的 URL。
    • 如果您在应用程序启动后更改 bundleURL 变量的逻辑,那么此更改将仅影响您的应用程序。在这种情况下,请将更新变量的逻辑移动到 AppDelegate 中的 bundleURL 函数

请参阅完整的更改日志以获取完整的重大变更列表。

已知问题

iOS

  • 当使用多个窗口时存在边缘情况:当主窗口处于非活动状态且系统尝试显示对话框时,对话框不会显示在屏幕上的正确位置。修复将在 #44167 中推出,并将在 0.74.1 中发布。

致谢

React Native 0.74 包含来自 57 位贡献者的 1673 个提交。感谢大家的辛勤工作!

升级至 0.74

请使用 React Native Upgrade Helper 查看现有项目在 React Native 版本之间的代码更改,除了升级文档

要创建一个新项目:

npx react-native@latest init MyProject  

如果您使用 Expo,React Native 0.74 将在 Expo SDK 51 中支持。

信息

0.74 现在是 React Native 的最新稳定版本,而 0.71.x 被移至不受支持状态。有关更多信息,请参阅 React Native 的支持政策。我们计划在五月初发布 0.71 的最终生命周期更新。

分享于 2024-04-23

访问量 79

预览图片