跳至主要內容

React Native 0.75 - 支援版面配置中的百分比值、New Architecture 穩定化、範本與初始化更新及更多功能

·14 分鐘閱讀時間
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol
Expo 軟體工程師
Siddharth Kulkarni
Siddharth Kulkarni
Coinbase 軟體工程師
Thibault Malbranche
Thibault Malbranche
Brigad 首席行動工程師
Blake Friedman
Blake Friedman
Meta 軟體工程師
Riccardo Cipolleschi
Riccardo Cipolleschi
Meta 軟體工程師
Nicola Corti
Nicola Corti
Meta 軟體工程師

今天我們很高興發佈 React Native 0.75!

此版本推出多項功能,例如支援 % 值的 Yoga 3.1、多項 New Architecture 穩定化修正,以及為使用者導入使用 React Native 框架的建議。

重點功能

重大變更

重點功能

Yoga 3.1 和版面配置改進

自從我們上次在 React Native 0.74 中發佈 Yoga 3.0 版以來,我們持續為您的應用程式推動許多改進和新的版面配置功能。React Native 0.75 隨附 Yoga 3.1,您可以在 Yoga 官方的發佈部落格文章中深入瞭解新功能。

一項值得注意且廣受要求的功能是在各種位置支援 % 值,例如 gapstranslation

資訊

這些功能僅適用於 New Architecture。如果您渴望使用這些功能,請考慮遷移至 New Architecture。

間距中的百分比值

在 0.75 版本中,此處描述的 gapcolumnGaprowGap 屬性現在支援具有 % 值的字串。

例如

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>
);
}

將呈現如下

AndroidiOS
Android GapsiOS Gaps

平移中的百分比值

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>
);
}

將呈現如下

AndroidiOS
Android TranslationiOS Translation

New Architecture 穩定化

自從我們在 React Conf 上宣佈 New Architecture 進入 Beta 版以來,我們發佈了多項錯誤修正和穩定性改進。

我們的目標是讓 New Architecture 在不久的將來被視為穩定。因此,在過去幾個月中,我們專注於彌合舊架構和 New Architecture 之間的差距。我們修正的一些錯誤和遺失功能範例包括

  • 修正 Android 上的 adjustsFontSizeToFit (#44075)
  • 修正 textAlign 在 Android 上不適用於內嵌檢視的問題 (#44146)
  • 修正 iOS 上文字基準線向上移動的問題 (#44932)

我們也與 Expo 的人員合作,在 React Native Directory 中新增了有關 New Architecture 支援的資訊,以便您立即清楚瞭解程式庫是否已支援 New Architecture

React Native Directory

我們也邀請您參與 New Architecture 問卷調查。此問卷調查對於我們收集有關 New Architecture 推出後續步驟的寶貴意見反應至關重要。

我們也想分享我們在 New Architecture 工作群組中發佈的一篇文章,內容關於 在 New Architecture 中支援 UIManager。這篇文章概述了 Android 上 UIManager API 的 API,以及它如何協助遷移更進階的應用程式和程式庫。

此版本還包含一個新的 API,現在是存取 jsi::Runtime 的官方方式。

在 TurboModules 中存取 jsi::Runtime

過去,從原生模組存取 jsi::Runtime 從來沒有建議的方式,使用者會繞過框架以冒險的方式執行此操作。在 0.74 版本中,我們推出了實驗性 API,提供對 jsi::Runtime 的安全存取,我們很高興宣佈它們在 0.75 版本中已穩定。

有關如何存取 jsi::Runtime 的範例

在 iOS 上,您可以讓您的 Turbo 原生模組符合協定 RCTTurboModuleWithJSIBindings。您現在可以實作 installJSIBindingsWithRuntime,這將讓您可以安全地執行緒存取執行階段。

@interface RCTSampleTurbo Module () <RCTTurboModuleWithJSIBindings>
@end

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

在 Android 上,您可以讓您的 Turbo 原生模組符合介面 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) {
// do stuff on JS thread
}

在 Android 上,CallInvoker 可透過 ReactContext 在名為 CallInvokerHolder 的 JNI 包裝函式中存取,您可以在跨越 JNI 邊界後呼叫 invokeAsync

// Java
public abstract CallInvokerHolder getJSCallInvokerHolder();
// C++
jsCallInvokerHolder->cthis()->getCallInvoker()->invokeAsync([&](jsi::Runtime& rt) {
// do stuff on JS thread
});

使用框架

正如我們今年稍早在 React Conf 上分享的,現在建置 React Native 應用程式的建議方式是透過框架,例如 Expo。

您可以在我們之前的部落格文章中閱讀有關此指南的更多資訊:「使用框架來建置 React Native 應用程式」。

我們希望為新的 React Native 使用者設定成功的基礎。我們相信,使用框架可讓您盡可能提高生產力,並在建置新應用程式時為您提供最佳的開發人員體驗。

為了反映這些建議,此版本包含下列變更

  • 我們將 /template 資料夾從 react-native 套件移至個別的儲存庫:react-native-community/template
  • 我們將於 2024 年 12 月 31 日停止使用 react-native init 命令。

如果您已經使用框架 (例如 Expo),這些變更完全不會影響您。您可以將 React Native 0.75 與 Expo SDK 51 一起使用 (您可以在 此 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 configinit 以外的所有其他命令將繼續照常運作。

資訊

為了提供更順暢的遷移體驗,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 的使用者。

我們在此處呈現它們是為了完整性和參考。

TypeScript 中的 Touchable 無法再用作泛型表示式中的類型

TouchablesOpacityTouchableHighlights 元件已轉換為函式元件。這表示它們無法再用作 value & type。因此,例如,以下內容不再有效

import {TouchableHighlight} from 'react-native';
const ref = useRef<TouchableHighlight>();
// ^^^ TS2749: TouchableHighlight refers to a value, but is being used as a type here.
// Did you mean typeof TouchableHighlight?

相反地,您應該使用內建的 React 類型 React.ElementRef,或替代方案,View 類型

import {TouchableHighlight} from 'react-native';
const ref1 =
useRef<React.ElementRef<typeof TouchableHighlight>>();
// or
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 版本。

從 React Native 0.76 開始,minSdk 版本將為 24 (Android 7.0),minIOSVersion 將為 15.1。

您可以在我們的官方公告中閱讀有關 Android 的更多資訊,以及有關 iOS 的更多資訊

Android:已刪除 JSIModule

com.facebook.react.bridge.JSIModule (來源) 是我們暫時推出的 API,允許原生模組直接在 Android 上存取 JSI。此 API 的存取器已在 0.74 版本中棄用,並且我們驗證過在開放原始碼中沒有對此 API 的有意義使用,因此我們在 0.75 版本中將其移除。您可以使用 Turbo 原生模組 作為替代方案。

Android:PopUp Menu 已移至個別套件

在 0.74 版本中,我們將 Android 的 PopUpMenu 移至 @react-native 範圍下的個別套件。在 0.75 版本中,我們將移除核心中剩餘的方法

  • UIManagerModule.showPopupMenu()
  • UIManagerModule.dismissPopupMenu()

作為替代方案,請使用 <PopupMenuAndroid /> 元件,該元件位於 @react-native/popup-menu-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-bundleprofile-hermes

ram-bundle 命令在 React Native 0.59 中推出,可讓您透過直接在記憶體中載入套件來執行套件。此功能現在已由我們的預設 JS 引擎 Hermes 取代。您不應使用 ram-bundle 命令。

profile-hermes 命令是一個工具,可協助您分析 JavaScript 程式碼的 CPU 效能。這使用了舊的 .cpuprofile 格式,Chrome 的最新版本不再支援該格式。將此功能作為獨立命令包含在內也是我們正在逐步淘汰的做法,因為我們致力於提高偵錯工具的品質標準。CPU 分析現在可以從實驗性新偵錯器中的「分析器」面板存取 (注意:如果從 Chrome 連線到 Hermes,則無法存取)。

其他重大變更

一般

  • Codegen
    • 稍微變更了純 C++ TurboModules 產生類別和結構的名稱。我們從其名稱中刪除了 Cxx 符號
    • 由於可能發生精確度錯誤,因此不再支援浮點列舉
    • 當在 JS 中將 null 傳遞給原生中的非可為 Null 引數時,擲回錯誤
  • Linting
    • ESLint 設定在執行 linting 時不再執行 prettier
  • C++
    • ScrollViewShadowNode 現在需要在建構函式中使用新的 bool includeTransform 參數
    • 從 RuntimeExecutor 中移除 executeAsynchronouslyexecuteSynchronously_CAN_DEADLOCK
    • JsErrorHandler.h 中將 JsErrorHandlingFunc 重新命名為 OnJsError
    • handleFatalError.h 中將 handleJsError 重新命名為 OnJsError
    • ReactPrimitives.h 中移除未使用的 import
    • LongLivedObjectCollectionLongLivedObject 取得方法現在接受 Runtime 參數
    • utils/jsi.h 檔案重新命名為 jsi-utils.h
  • TextInput
    • 移除已棄用的 onTextInput 回呼
  • Pressability
    • 移除 onLongPressShouldCancelPress_DEPRECATEDonResponderTerminationRequest_DEPRECATEDonStartShouldSetResponder_DEPRECATED 方法

Android

  • ReactViewBackgroundDrawable
    • 已棄用,改用 CSSBackgroundDrawable。這也會從 ReactViewBackgroundDrawableColorUtil 中移除一些 API
  • ReactContext
    • ReactContextReactApplicationContext 現在是抽象的。請改用 BridgeReactContextBridgelessReactContext
    • 刪除 ReactContext.initializeWithInstance()。請改用 BridgeReactInstance
    • BridgelessReactContext.getJavaScriptContextHolder() 中移除。請改用 BridgelessCatalystInstance
    • 移除 ReactContext.getRuntimeExecutor()。請使用 BridgelessCatalystInstance
  • 版面配置
    • 支援百分比彈性間距值。這會將某些方法 (例如 setGapsetRowGapsetColumnGap) 的參數從 float 變更為 dynamic
    • 需要在 Android Manifest 中 supportsRTL
  • Runtime
    • 從 ReactHostImpl 中移除 ReactJsExceptionHandler
    • 讓應用程式負責在不使用預設範本時傳回核心 turbomodules
  • DevSupport
    • 變更 DevSupportManagerFactory.create() 以接受新的 PausedInDebuggerOverlayManager 參數
  • Measurement
    • 已刪除 UIManagerModule.measureLayoutRelativeToParent()

iOS

  • Runtime
    • 移除 [RCTHost getSurfacePresenter][RCTHost getModuleRegistry]
    • 移除 EventPriority 類別,並一律使用預設 EventPriority::AsynchronousBatched。如果建置失敗,請移除任何 EventPriority 的使用
  • Image
    • 移除未使用的 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 次提交。感謝您的辛勤工作!

感謝所有其他作者為此版本文章中的功能編寫文件

升級至 0.75

除了升級文件外,請使用 React Native 升級助手,以檢視現有專案中 React Native 版本之間的程式碼變更。

若要建立新專案

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

如果您使用 Expo,Expo SDK 51 將支援 React Native 0.75 版本 (關於如何在您的 Expo 專案中將 React Native 更新到 0.75.0 版本的說明,請參閱這篇專文)。

資訊

0.75 現在是 React Native 最新的穩定版本,而 0.72.x 版本將不再受支援。如需更多資訊,請參閱 React Native 的支援政策。我們的目標是在不久的將來發布 0.72 版本的最終終止支援更新。