React Native 0.75 -支持布局中的百分比值,新架構穩定,模板和初始化更新等


今天,我們很高興發布 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 版本中,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>
  );
}
  • 將渲染如下:

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)
  • 與 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 進行更高級操作的小部分用戶。

為了完整性和參考,我們在這里列出了它們。

  1. Touchable 組件在 TypeScript 中不再能用作泛型表達式中的類型

    • TouchableOpacityTouchableHighlight 組件已轉換為函數組件。這意味著它們不能再用作值和類型。因此,例如,以下代碼不再有效:
    import {TouchableHighlight} from 'react-native';
    const ref = useRef<TouchableHighlight>();
    //                ^^^ TS2749: TouchableHighlight 指的是一個值,但在這里被用作類型。
    //                            您是否是指 `typeof TouchableHighlight`?
    
    • 相反,您應該使用內置的 React 類型 React.ElementRefView 類型:
    import {TouchableHighlight} from 'react-native';
    const ref1 =
      useRef<React.ElementRef<typeof TouchableHighlight>>(); 
    // 或
    const ref2 = useRef<View>();
    
  2. 最后支持 minSdk 23minIOSVersion 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 的官方公告中閱讀更多內容。

  3. 刪除 Android 的 JSIModule

    • com.facebook.react.bridge.JSIModule 是一個 API,我們臨時引入了它以便原生模塊能夠直接在 Android 上訪問 JSI。該 API 的訪問器在 0.74 中已被棄用,我們驗證了在開源中沒有對該 API 的有意義的使用,因此我們在 0.75 中將其移除。您可以使用 Turbo Native Modules 作為替代方案。
  4. 將 Android 的 PopUp Menu 移至單獨的包

    • 在 0.74 版本中,我們將 Android 的 PopUpMenu 移至 @react-native 范圍下的單獨包。在 0.75 版本中,我們移除了核心中仍存在的剩余方法:
    UIManagerModule.showPopupMenu()
    UIManagerModule.dismissPopupMenu()
    
    • 作為替代方案,請使用位于 @react-native/popup-menu-android 包中的 <PopupMenuAndroid /> 組件。
  5. 完成 iOS PushNotificationIOS 的棄用工作

    • 在 0.74 版本中,我們棄用了 PushNotificationIOS 模塊中的一些 API。

    • 在 0.75 版本中,我們刪除了這些 API 以遷移離開舊的通知元數據表示。

    • 刪除的 API 包括:

      + (void)didReceiveLocalNotification:(UILocalNotification *)notification;
      + (void)didReceiveRemoteNotification:(NSDictionary *)notification;
      
    • 相反,使用 didReceiveNotification:(UNNotification *)notification

  6. 社區 CLI:刪除 ram-bundleprofile-hermes 命令

    • 我們想要宣布社區 CLI 中的兩個重大移除:ram-bundleprofile-hermes 命令。
    • ram-bundle 命令是在 React Native 0.59 中引入的,用于直接在內存中加載運行包。此功能現在由我們的默認 JS 引擎 Hermes 取代。您不應再使用 ram-bundle 命令。
    • profile-hermes 命令是一個幫助您分析 JavaScript 代碼 CPU 性能的工具。它使用的是舊的 .cpuprofile 格式,最近版本的 Chrome 不再支持該格式。將此功能作為一個獨立命令也是我們正在逐步淘汰的,因為我們致力于提高調試工具的質量標準。現在可以通過“Profiler”面板在實驗性新調試器中訪問 CPU 分析功能(注意:如果從 Chrome 連接到 Hermes,則無法訪問此功能)。

其他重大變更

通用

  1. 代碼生成:

    • 略微更改了純 C++ TurboModules 生成的類和結構的名稱。我們從名稱中刪除了 "Cxx" 代號。
    • 由于可能的精度問題,不再支持浮點枚舉。
    • 當在 JS 中傳遞 null 給原生代碼中的非可空參數時,現在會拋出錯誤。
  2. 代碼檢查:

    • 在進行 ESLint 配置檢查時,不再運行 prettier
  3. C++:

    • ScrollViewShadowNode 的構造函數現在需要一個新的布爾參數 includeTransform
    • 移除了 RuntimeExecutor 中的 executeAsynchronouslyexecuteSynchronously_CAN_DEADLOCK
    • JsErrorHandler.h 中將 JsErrorHandlingFunc 重命名為 OnJsError
    • handleFatalError.h 中將 handleJsError 重命名為 OnJsError
    • ReactPrimitives.h 中移除了未使用的導入。
    • LongLivedObjectCollectionLongLivedObjectget 方法現在接受一個 Runtime 參數。
    • utils/jsi.h 文件重命名為 jsi-utils.h
  4. TextInput:

    • 移除了已棄用的 onTextInput 回調。
  5. Pressability:

    • 移除了 onLongPressShouldCancelPress_DEPRECATEDonResponderTerminationRequest_DEPRECATEDonStartShouldSetResponder_DEPRECATED 方法。

Android

  1. ReactViewBackgroundDrawable:

    • 已棄用,改用 CSSBackgroundDrawable。這也移除了 ReactViewBackgroundDrawableColorUtil 中的一些 API。
  2. ReactContext:

    • ReactContextReactApplicationContext 現在是抽象類。請使用 BridgeReactContextBridgelessReactContext
    • 刪除了 ReactContext.initializeWithInstance()。請使用 BridgeReactInstance 代替。
    • BridgelessReactContext 中移除了 getJavaScriptContextHolder()。請使用 BridgelessCatalystInstance 代替。
    • 移除了 ReactContext.getRuntimeExecutor()。請使用 BridgelessCatalystInstance
  3. 布局:

    • 支持百分比的 flex gap 值。這些更改影響了一些方法的參數,如 setGapsetRowGapsetColumnGap 的類型從 float 改為 dynamic
    • 在 Android Manifest 中要求支持 RTL(從右到左布局)。
  4. 運行時:

    • ReactHostImpl 中移除了 ReactJsExceptionHandler
    • 當不使用默認模板時,應用程序需要負責返回核心 TurboModules。
  5. 開發支持:

    • 更改了 DevSupportManagerFactory.create(),使其接受一個新的 PausedInDebuggerOverlayManager 參數。
  6. 測量:

    • 刪除了 UIManagerModule.measureLayoutRelativeToParent()

iOS

  1. 運行時:

    • 移除了 [RCTHost getSurfacePresenter][RCTHost getModuleRegistry]
    • 移除了 EventPriority 類,并始終使用默認的 EventPriority::AsynchronousBatched。如果構建失敗,請刪除任何 EventPriority 的使用。
  2. 圖像:

    • 移除了未使用的 RCTImageLoadingPerfInstrumentationEnabled
  3. 錯誤處理:

    • 移除了通過 RCTBridge 訪問 RCTRedBox 的能力。
  4. CocoaPods:

    • BUILD_FROM_SOURCE 重命名為 RCT_BUILD_HERMES_FROM_SOURCE
    • React-Codegen 重命名為 ReactCodegen,以便更好地兼容 use_frameworksSwift
  5. 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 23minIOSVersion 13.4 的版本工作。
  • Kudo Chien:為自動鏈接性能改進。
  • Alex Hunt:為移除 ram-bundleprofile-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 的說明可在專門的文章中找到)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容