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 版本中,将能够更细粒度地配置布局一致性。
React Native 以前翻转 在处理 row-reverse
容器上设置的 margin
、padding
或 border
时的 left
/right
(以及 start
/end
)边缘。现在,这些属性的行为与 Web 保持一致。以前依赖于边缘反转的代码可能需要更新才能继续正确渲染。
样式 | 之前 | 之后 |
---|---|---|
|
支持 align-content: 'space-evenly'
Yoga 3.0 带来了对 alignContent: 'space-evenly'
的支持。space-evenly
使用均匀间隔的间隙在多行弹性容器中分布行,并放置在行和容器边缘之间。
支持 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 的用户通知框架,并公开了用于计划和处理通知的新 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 文档)。
- (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 调试器仍然是我们推荐的 0.74 调试选项。您还可以尝试实验性新调试器,它也是 Expo 中的默认调试器。这仍然是一个早期预览版 - 可以在此处跟踪已知问题和更新。
其他重大更改
通用
- 使样式中的
start
/end
始终引用书写方向(#42251)。
Android
- 移除
FabricUIManagerProvider
中的JSIModule*
(#42059).- 此 API 在开源版本中未使用 - 请改用 TurboModules。
- 弃用
UIManagerModule.showPopupMenu
和UIManagerModule.dismissPopupMenu
(#42441)- 此 API 已移至
@react-native/popup-menu-android
npm 包中,并将在 0.75 版本中移除。
- 此 API 已移至
iOS
- 从 iOS 代码生成 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 的最终生命周期结束更新。