今天,我們很高興發布 React Native 0.75!
此版本包含多個新功能,如支持 % 值的 Yoga 3.1、新架構的多個穩定性修復,以及建議用戶使用 React Native 框架。
主要亮點
1. Yoga 3.1 和布局改進:
- 自從我們在 React Native 0.74 中發布 Yoga 3.0 以來,我們不斷推出許多改進和新布局功能。React Native 0.75 隨附 Yoga 3.1,您可以在 Yoga 的官方發布博客中了解更多新內容。
- 一個顯著且備受期待的功能是對 % 值的支持,可用于間隙和變換等多個地方。
提示:這些功能僅適用于新架構。如果您希望使用它們,請考慮遷移到新架構。
2. 百分比值在間隙中的應用:
- 在 0.75 版本中,
gap
、columnGap
和rowGap
屬性現在支持帶 % 值的字符串。例如:
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. 百分比值在變換中的應用:
-
transform
屬性現在也可以接受 % 作為translate
變換的值。例如,以下組件會將紅色方塊的 X 坐標移動其寬度的 100%,Y 坐標移動其高度的 100%:
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. 新架構穩定化:
- 自我們在 React Conf 上宣布新架構進入 Beta 以來,我們發布了多個 Bug 修復并改善了其穩定性。
- 我們的目標是在不久的將來將新架構視為穩定。因此,過去幾個月中我們專注于彌合舊架構和新架構之間的差距。我們修復了一些 Bug 和缺失的功能,例如:
- 修復了 Android 上的
adjustsFontSizeToFit
(#44075) - 修復了 Android 上
textAlign
在內聯視圖中不起作用的問題(#44146) - 修復了 iOS 上文本基線被抬高的問題(#44932)
- 修復了 Android 上的
- 與 Expo 團隊合作,我們還在 React Native 目錄中添加了有關新架構支持的信息,因此您可以立即了解某個庫是否已經支持新架構:
- 我們還邀請您參加新架構調查問卷。這項調查對我們至關重要,有助于我們收集有關新架構推廣下一步的寶貴反饋。
- 我們還想分享我們在新架構工作組中發布的一篇關于在新架構中支持 UIManager 的文章。本文提供了 Android 上 UIManager API 的概述,并解釋了它如何幫助更高級的應用程序和庫遷移。
5. 訪問 jsi::Runtime 的新 API:
- 過去,沒有官方推薦的方式讓原生模塊訪問 jsi::Runtime,開發者通常會通過一些冒險的方法繞過框架。在 0.74 中,我們引入了實驗性 API 提供對 jsi::Runtime 的安全訪問,我們很高興地宣布這些 API 在 0.75 中已穩定。
訪問 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 用戶創造成功的基礎。我們相信,使用框架可以讓您盡可能高效,并在構建新應用程序時為您提供最佳的開發者體驗。
為了反映這些建議,此版本包含以下更改:
- 我們將
/template
文件夾從react-native
包中移至一個獨立的存儲庫:react-native-community/template
。 - 我們將于 2024 年 12 月 31 日停止使用
react-native init
命令。
如果您已經在使用像 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
命令將不再創建項目。您將需要選擇:
- 使用框架(如 Expo),并使用其專用命令創建新項目,如
npx create-expo-app
。 - 直接使用社區 CLI 通過
npx @react-native-community/cli 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 進行更高級操作的小部分用戶。
為了完整性和參考,我們在這里列出了它們。
-
Touchable 組件在 TypeScript 中不再能用作泛型表達式中的類型:
-
TouchableOpacity
和TouchableHighlight
組件已轉換為函數組件。這意味著它們不能再用作值和類型。因此,例如,以下代碼不再有效:
import {TouchableHighlight} from 'react-native'; const ref = useRef<TouchableHighlight>(); // ^^^ TS2749: TouchableHighlight 指的是一個值,但在這里被用作類型。 // 您是否是指 `typeof TouchableHighlight`?
- 相反,您應該使用內置的 React 類型
React.ElementRef
或View
類型:
import {TouchableHighlight} from 'react-native'; const ref1 = useRef<React.ElementRef<typeof TouchableHighlight>>(); // 或 const ref2 = useRef<View>();
-
-
最后支持
minSdk 23
和minIOSVersion 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 的官方公告中閱讀更多內容。
- 這些并不是 0.75 版本本身的重大更改,但我們希望告知您,React Native 0.75 將是最后一個支持
-
刪除 Android 的
JSIModule
:-
com.facebook.react.bridge.JSIModule
是一個 API,我們臨時引入了它以便原生模塊能夠直接在 Android 上訪問 JSI。該 API 的訪問器在 0.74 中已被棄用,我們驗證了在開源中沒有對該 API 的有意義的使用,因此我們在 0.75 中將其移除。您可以使用 Turbo Native Modules 作為替代方案。
-
-
將 Android 的
PopUp Menu
移至單獨的包:- 在 0.74 版本中,我們將 Android 的
PopUpMenu
移至@react-native
范圍下的單獨包。在 0.75 版本中,我們移除了核心中仍存在的剩余方法:
UIManagerModule.showPopupMenu() UIManagerModule.dismissPopupMenu()
- 作為替代方案,請使用位于
@react-native/popup-menu-android
包中的<PopupMenuAndroid />
組件。
- 在 0.74 版本中,我們將 Android 的
-
完成 iOS
PushNotificationIOS
的棄用工作:在 0.74 版本中,我們棄用了
PushNotificationIOS
模塊中的一些 API。在 0.75 版本中,我們刪除了這些 API 以遷移離開舊的通知元數據表示。
-
刪除的 API 包括:
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification; + (void)didReceiveRemoteNotification:(NSDictionary *)notification;
相反,使用
didReceiveNotification:(UNNotification *)notification
。
-
社區 CLI:刪除
ram-bundle
和profile-hermes
命令:- 我們想要宣布社區 CLI 中的兩個重大移除:
ram-bundle
和profile-hermes
命令。 -
ram-bundle
命令是在 React Native 0.59 中引入的,用于直接在內存中加載運行包。此功能現在由我們的默認 JS 引擎 Hermes 取代。您不應再使用ram-bundle
命令。 -
profile-hermes
命令是一個幫助您分析 JavaScript 代碼 CPU 性能的工具。它使用的是舊的.cpuprofile
格式,最近版本的 Chrome 不再支持該格式。將此功能作為一個獨立命令也是我們正在逐步淘汰的,因為我們致力于提高調試工具的質量標準。現在可以通過“Profiler”面板在實驗性新調試器中訪問 CPU 分析功能(注意:如果從 Chrome 連接到 Hermes,則無法訪問此功能)。
- 我們想要宣布社區 CLI 中的兩個重大移除:
其他重大變更
通用
-
代碼生成:
- 略微更改了純 C++ TurboModules 生成的類和結構的名稱。我們從名稱中刪除了 "Cxx" 代號。
- 由于可能的精度問題,不再支持浮點枚舉。
- 當在 JS 中傳遞
null
給原生代碼中的非可空參數時,現在會拋出錯誤。
-
代碼檢查:
- 在進行 ESLint 配置檢查時,不再運行
prettier
。
- 在進行 ESLint 配置檢查時,不再運行
-
C++:
-
ScrollViewShadowNode
的構造函數現在需要一個新的布爾參數includeTransform
。 - 移除了
RuntimeExecutor
中的executeAsynchronously
和executeSynchronously_CAN_DEADLOCK
。 - 在
JsErrorHandler.h
中將JsErrorHandlingFunc
重命名為OnJsError
。 - 在
handleFatalError.h
中將handleJsError
重命名為OnJsError
。 - 從
ReactPrimitives.h
中移除了未使用的導入。 -
LongLivedObjectCollection
和LongLivedObject
的get
方法現在接受一個Runtime
參數。 - 將
utils/jsi.h
文件重命名為jsi-utils.h
。
-
-
TextInput:
- 移除了已棄用的
onTextInput
回調。
- 移除了已棄用的
-
Pressability:
- 移除了
onLongPressShouldCancelPress_DEPRECATED
、onResponderTerminationRequest_DEPRECATED
和onStartShouldSetResponder_DEPRECATED
方法。
- 移除了
Android
-
ReactViewBackgroundDrawable:
- 已棄用,改用
CSSBackgroundDrawable
。這也移除了ReactViewBackgroundDrawable
和ColorUtil
中的一些 API。
- 已棄用,改用
-
ReactContext:
-
ReactContext
和ReactApplicationContext
現在是抽象類。請使用BridgeReactContext
和BridgelessReactContext
。 - 刪除了
ReactContext.initializeWithInstance()
。請使用BridgeReactInstance
代替。 - 從
BridgelessReactContext
中移除了getJavaScriptContextHolder()
。請使用BridgelessCatalystInstance
代替。 - 移除了
ReactContext.getRuntimeExecutor()
。請使用BridgelessCatalystInstance
。
-
-
布局:
- 支持百分比的
flex gap
值。這些更改影響了一些方法的參數,如setGap
、setRowGap
和setColumnGap
的類型從float
改為dynamic
。 - 在 Android Manifest 中要求支持
RTL
(從右到左布局)。
- 支持百分比的
-
運行時:
- 從
ReactHostImpl
中移除了ReactJsExceptionHandler
。 - 當不使用默認模板時,應用程序需要負責返回核心 TurboModules。
- 從
-
開發支持:
- 更改了
DevSupportManagerFactory.create()
,使其接受一個新的PausedInDebuggerOverlayManager
參數。
- 更改了
-
測量:
- 刪除了
UIManagerModule.measureLayoutRelativeToParent()
。
- 刪除了
iOS
-
運行時:
- 移除了
[RCTHost getSurfacePresenter]
和[RCTHost getModuleRegistry]
。 - 移除了
EventPriority
類,并始終使用默認的EventPriority::AsynchronousBatched
。如果構建失敗,請刪除任何EventPriority
的使用。
- 移除了
-
圖像:
- 移除了未使用的
RCTImageLoadingPerfInstrumentationEnabled
。
- 移除了未使用的
-
錯誤處理:
- 移除了通過
RCTBridge
訪問RCTRedBox
的能力。
- 移除了通過
-
CocoaPods:
- 將
BUILD_FROM_SOURCE
重命名為RCT_BUILD_HERMES_FROM_SOURCE
。 - 將
React-Codegen
重命名為ReactCodegen
,以便更好地兼容use_frameworks
和Swift
。
- 將
-
TextInput:
- 移除了已棄用的
onTextInput
回調。
- 移除了已棄用的
鳴謝
React Native 0.75 包含了 165 位貢獻者的超過 1491 次提交。感謝大家的辛勤工作!
特別感謝在此版本發布文檔中對功能進行了記錄的所有額外作者:
- Nick Gerleman 和 Joe Vilches:為 Yoga 3.1 和布局改進工作。
-
Arushi Kesarwani:為在新架構中支持
UIManager
。 -
Phillip Pan:為在 TurboModules 中訪問
jsi::Runtime
。 -
Alan Lee 和 Soe Lynn:為最后一個支持
minSdk 23
和minIOSVersion 13.4
的版本工作。 - Kudo Chien:為自動鏈接性能改進。
-
Alex Hunt:為移除
ram-bundle
和profile-hermes
命令。
升級至 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 的說明可在專門的文章中找到)。