React Native 0.74 - Yoga 3.0、无桥接新架构等
今天我们发布 React Native 0.74!此版本增加了 Yoga 3.0,在新架构下默认启用无桥接模式,批量 onLayout 更新(新架构),以及 Yarn 3 作为新项目的默认包管理器。
我们还移除了废弃的 API,包括 PropTypes 的移除和 PushNotificationIOS 的重大变更。在 Android 上,SDK 23(Android 6.0)现在是最低支持版本。
亮点
重大变更
- Android 最低 SDK 提升(Android 6.0)
- PushNotificationIOS 的 API 变更(已废弃)
- 移除废弃的
PropTypes - 移除 Flipper React Native 插件
- 其他破坏性变更
亮点
Yoga 3.0
新布局行为
React Native 0.74 包含 Yoga 3.0,这是我们布局引擎的最新版本。Yoga 3.0 通过使样式更具可预测性来改进布局,并支持渲染为 Web 编写的组件。
React Native 仍然有意保留了一些不正确的布局行为,因为发现修复它们会影响大量实际组件。未来的 React Native 版本将能够更精细地配置布局一致性。
| 样式 | 之前 | 之后 |
|---|---|---|
|
支持 align-content: 'space-evenly'
Yoga 3.0 带来对 alignContent: 'space-evenly' 的支持。space-evenly 使用均匀分布的间隙在多行 flex 容器中分布行,这些间隙放置在行和容器边缘之间。

支持 position: 'static'
position: 'static' 仅在新架构中支持。
标记为 position: 'static' 的元素可能无法偏移,并且在确定绝对定位元素的 包含块 时不予考虑。这允许将元素相对于不是其直接父级的祖先进行定位。
|
请注意,绿色的 <View> 声明了 left 和 top,并且它是相对于蓝色的 <View> 定位的,而不是其父级。
当未设置 position 时,React Native 仍然默认为 position: 'relative'。
新架构:默认无桥接
在此版本中,当新架构启用时,我们将无桥接模式设为默认。您可以在此帖子中了解更多关于我们切换到默认无桥接的信息。为了使过渡更顺畅,我们增强了互操作层以覆盖无桥接,并与多个库合作,确保它们从第一天起就能在无桥接模式下工作。
无桥接并不是我们唯一从事的互操作层:我们还改进了新渲染器互操作层。最令人兴奋的是,它现在默认启用:您无需指定需要通过它的组件!您可以在此处阅读更多信息。
最后,如果您想了解更多关于新架构的信息,可以在 react-native-new-architecture 仓库中找到文档。当新架构成为默认时,此信息将被整合到 reactnative.dev。
新架构:批量 onLayout 更新
onLayout 回调中的状态更新现在是批处理的。以前,onLayout 事件中的每个状态更新都会导致新的渲染提交。
function MyComponent(props) {
const [state1, setState1] = useState(false);
const [state2, setState2] = useState(false);
return (
<View>
<View
onLayout={() => {
setState1(true);
}}>
<View
onLayout={() => {
// When this event is executed, state1's new value is no longer observable here.
setState2(true);
}}>
</View>
</View>
);
}
在 0.74 中,setState1 和 setState2 更新是批量处理的。此更改是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。

移除已弃用的 PropTypes
在 0.74 之前,React Native 继续提供 PropTypes,这是一个自 2017 年 React 15.5 以来就被弃用的 API!我们现在正在从 React Native 中移除所有内置的 PropTypes,从而减小应用大小(缩小包中为 26.4kB)和内存开销。
以下 PropTypes 属性已被移除:Image.propTypes、Text.propTypes、TextInput.propTypes、ColorPropType、EdgeInsetsPropType、PointPropType、ViewPropTypes(参见提交)。
如果您的应用程序或库依赖于 PropTypes,我们强烈建议迁移到像 TypeScript 这样的类型系统。
PushNotificationIOS (已弃用) 的 API 更改
在 React Native 0.74 中,我们正在采取措施移除已弃用的 PushNotificationIOS 库。此版本中的更改主要集中在移除对旧 iOS API 的引用。PushNotificationIOS 已迁移到 Apple 的 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 上的属性已更改。alertAction 和 repeatInterval 现已弃用,并将在 0.75 中移除
type Notification = {
...
// NEW: Seconds from now to display the notification.
fireIntervalSeconds?: ?number,
// CHANGED: Used only for scheduling notifications. Will be null when
// retrieving notifications using `getScheduledLocalNotifications` or
// `getDeliveredNotifications`.
soundName?: ?string,
// DEPRECATED: This was used for iOS's legacy UILocalNotification.
alertAction?: ?string,
// DEPRECATED: Use `fireDate` or `fireIntervalSeconds` instead.
repeatInterval?: ?string,
};
最后,PushNotificationIOS.removeEventListener 上的 handler 参数未使用,已被移除。
💡 如何迁移
iOS
您的 AppDelegate 需要实现 UNUserNotificationCenterDelegate。这应该在应用程序启动时在 application:willFinishLaunchingWithOptions: 或 application:didFinishLaunchingWithOptions: 中完成(有关更多详细信息,请参阅 Apple Docs)。
- (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
{
// This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
[RCTPushNotificationManager didReceiveNotification:notification];
// Decide if and how the notification will be shown to the user
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
{
// This condition passes if the notification was tapped to launch the app
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
// Allow the notification to be retrieved on the JS side using getInitialNotification()
[RCTPushNotificationManager setInitialNotification:response.notification];
}
// This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
[RCTPushNotificationManager didReceiveNotification:response.notification];
completionHandler();
}
最后,删除以下方法,并将逻辑调整到将代替调用的上述回调中。
application:didReceiveLocalNotification:[已弃用]application:didReceiveRemoteNotification:[已弃用]application:didReceiveRemoteNotification:fetchCompletionHandler:[未弃用,但已被UNUserNotificationCenterDelegate方法取代]
同时删除 application:didRegisterUserNotificationSettings: 和 RCTPushNotificationManager 对应的 didRegisterUserNotificationSettings: 的任何用法。
示例: 请参阅 RNTester 的 AppDelegate.mm。
JS
- 移除所有对
alertAction的引用。 - 移除所有对
removeEventListener的调用中的handler参数。 - 将所有
repeatInterval的用法替换为使用fireDate或fireIntervalSeconds触发多个通知。 - 请注意,当从
getScheduledLocalNotifications()和getDeliveredNotifications()返回的Notification上访问soundName时,它将为 null。
移除 Flipper React Native 插件
现在不再支持使用 Flipper 检查 React Native 布局、网络请求和其他 React Native 插件功能。在 0.74 中,我们已从新的 React Native 项目中移除了原生的 Flipper 库和设置代码。这意味着更少的依赖项和更快的本地设置(请参阅原始 RFC)。
在 升级助手 中可以看到从您的应用程序中移除 Flipper 的差异。如果您想在现有应用程序中保留 Flipper,请忽略相关的差异行。
💡 如何重新集成 Flipper
Flipper 仍可作为独立的工具用于调试 Android 或 iOS 应用,并通过遵循 Flipper 文档(Android 指南,iOS 指南)手动集成。
我们建议团队投入精力,转向 Android Studio 和 Xcode 中的原生调试工具。
替换 Flipper
有许多专用的调试工具可以替代 Flipper 的功能。有关更多信息,我们建议阅读 Jamon Holmgren 撰写的精彩文章 为什么你的 React Native 应用不需要 Flipper,以及如何没有它也能运行。
JavaScript 调试
使用 Hermes Debugger 仍然是我们 0.74 推荐的调试选项。您也可以尝试 实验性新调试器,它也是 Expo 中的默认选项。这仍然是早期预览版——已知问题和更新可以在此处查看。
其他重大变更
通用
- 使样式中的
start/end始终指向书写方向(#42251)。
Android
- 从
FabricUIManagerProvider中移除JSIModule*(#42059)。- 此 API 在开源中未使用——请改用 TurboModules。
- 弃用
UIManagerModule.showPopupMenu和UIManagerModule.dismissPopupMenu(#42441)- 此 API 已移至
@react-native/popup-menu-androidnpm 包,并将在 0.75 中移除。
- 此 API 已移至
iOS
- 删除 iOS codegen CLI 中的
configFilename和configKey参数(#41533)。 - 更改
bundleURL的处理方式(#43994)。- 以前,
bundleURL在 React Native 以实例变量启动时设置,无法更新。 - 现在,
bundleUrl是一个函数,它在需要时重新评估,从而实现在刷新时使用不同的 URL。 - 此更改仅在您在应用程序启动后更改
bundleURL变量时影响您的应用程序。在这种情况下,将更新变量的逻辑移动到AppDelegate中的bundleURL函数中。
- 以前,
请参阅完整更新日志以获取完整的破坏性变更列表。
已知问题
iOS
- 使用多个窗口时的边缘情况:当主窗口不活动且系统尝试显示对话框时,对话框未在屏幕上的正确位置显示。修复正在 #44167 中,并将在 0.74.1 中发布。
致谢
React Native 0.74 包含来自 57 位贡献者的超过 1673 次提交。感谢大家的辛勤工作!
感谢所有为本版本发布文章撰写文档的额外作者
- Nick Gerleman 贡献 Yoga 3.0
- Joe Vilches 贡献 Yoga 3.0
- Riccardo Cipolleschi 贡献 新架构:默认无桥接
- Samuel Susla 贡献 新架构:批量
onLayout更新 - Tim Yung 贡献 移除已弃用的
PropTypes - Ingrid Wang 贡献 PushNotificationIOS (已弃用) 的 API 更改
升级到 0.74
除了升级文档外,请使用React Native 升级助手来查看现有项目在 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 的支持政策。我们计划在 5 月初发布 0.71 的最终停止支持更新。




