メインコンテンツへスキップ

React Native 0.77 - 新しいスタイリング機能、Androidの16KBページ対応、Swiftテンプレート

·16分で読めます
Vojtech Novak
Vojtech Novak
ソフトウェアエンジニア @ Expo
Mazen Chami
Mazen Chami
ソフトウェアエンジニア @ InfiniteRed
Blake Friedman
Blake Friedman
ソフトウェアエンジニア @ Meta
Rob Hogan
Rob Hogan
ソフトウェアエンジニア @ Meta

本日、React Native 0.77のリリースを発表できることを嬉しく思います!

このリリースでは、いくつかの機能が提供されます。display: contentsboxSizingmixBlendModeoutline関連プロパティなどの新しいスタイル機能により、より強力なレイアウトオプションを提供します。また、新しいAndroidデバイスとの互換性のためのAndroid 16KBページサポートも含まれます。さらに、コミュニティテンプレートをSwiftに移行して最新化するとともに、Objective-Cを好む開発者のためにObjective-Cとの互換性のサポートと維持を継続しています。

ハイライト

破壊的変更

ハイライト

より良いレイアウト、サイズ設定、ブレンドのための新しいCSS機能

React Native 0.77は、React NativeとWebを連携させるという目標をさらに推進します。アプリのレイアウト、サイズ設定、ブレンドをより細かく制御できる新しいCSSプロパティのサポートを追加しました。これらの変更は、複雑なレイアウトを簡素化し、テクスチャを追加し、アプリのアクセシビリティを向上させるのに役立ちます。

情報

これらの新機能はすべて、新しいアーキテクチャでのみ利用可能です。

display: contentsによるシンプルなレイアウト

display: contentsプロパティは、要素がレイアウト構造から消滅しながら、その子要素が親要素の直接の子要素であるかのようにレンダリングされることを可能にします。これは、レイアウトに影響を与えずに子要素にスタイルを適用したい場合、イベントを処理する必要があるラッパーコンポーネントを構築する場合、またはShadowTreeと対話する必要がある場合に、スタイリング目的で役立ちます。

技術的に言えば、display: contentsはレイアウトボックスを生成せずに要素をレンダリングしますが、要素の子要素のレイアウトボックスは保持します。display: contentsを持つ要素は、ビュー階層から事実上フラット化されます。

ウィジェットが押されたときにアラートを表示したいこの例を見てみましょう。コンテナビュー内に赤いWidgetがあります。

Container.jsx
function Container() {
return (
<View style={styles.container}>
<Widget />
</View>
);
}

display contents - setup

次に、実験的なポインタイベントを使用して、その下のコンポーネントが押されたときにユーザーに警告するという目的で、新しいAlertingラッパーコンポーネントを構築します。分かりやすくするために、このコンポーネントの背景は青色になっています。それは以下のコンポーネントのように見えるかもしれません。

Container.jsx
function Alerting({children}) {
return (
<View
style={{backgroundColor: 'blue'}}
onPointerDown={() => alert('Hello World!')}>
{children}
</View>
}

function Container() {
return (
<View style={styles.container}>
<Alerting>
<Widget />
</Alerting>
</View>
);
}

これは私たちが望むものではありません。Alertingは、子Widgetとは別に、独自の境界を持つ新しいレイアウトボックスを追加します。ラップしている要素のスタイルによっては、これは重大な視覚的および機能的変更をもたらす可能性があります。この例では、青い背景がタップに反応してアラートを出しますが、タップされたときに赤い「Hello World」ボックスだけがアラートを出すことを望んでいます。

before display contents

AlertingViewラッパーにdisplay: contentsを設定してもう一度試すと、ユーザーが元のWidgetの境界内で押した場合にのみアラートが表示されます。これは、Alertingが独自のボックスを追加しなくなったものの、Widgetからバブルアップされたポインタイベントを観察できるためです。

Container.jsx
function Alerting({children}) {
return (
<View
style={{display: 'contents'}}
onPointerDown={() => alert('Hello World!')}>
{children}
</View>
);
}

// ... function Container ...

after display contents

ボックスサイジング

boxSizingプロパティは、要素の様々なサイズ指定プロパティ(widthheightminWidthminHeightなど)がどのように計算されるかを定義します。boxSizingborder-boxの場合、これらのサイズは要素のボーダーボックスに適用されます。content-boxの場合、要素のコンテンツボックスに適用されます。デフォルト値はborder-boxで、これはWebのデフォルト値とは異なります。このプロパティがどのように機能するかについて詳しく知りたい場合は、Webドキュメントが良い情報源です。

警告

border-boxはこれまでずっとデフォルトであり、content-boxが追加されるまで唯一のboxSizing値でした。デフォルトを変更すると、突然いくつかのレイアウトが壊れる互換性のない変更になったでしょう。後方互換性を確保するために、デフォルト値としてborder-boxを維持することにしました。

border-boxcontent-boxの違いを理解するために、両方のViewpadding: 20borderWidth: 10が設定されている次の例を見てみましょう。border-boxを使用する場合、サイズ指定のためにボーダーとパディングを考慮します。content-boxを使用する場合、サイズ指定のためにコンテンツのみを考慮します。

after display contents

CSS mixBlendMode

mixBlendModeプロパティを使用すると、要素がスタッキングコンテキスト内の他の要素とどのように色をブレンドするかを制御できます。各ブレンド機能の完全な概要については、MDNドキュメントをご覧ください。

ブレンドするものをより細かく制御できるように、isolationプロパティも追加しました。Viewisolation: isolateを設定すると、そのViewスタッキングコンテキストを強制的に形成します。したがって、このプロパティを一部の祖先Viewに設定することで、mixBlendModeを持つ一部の子孫View分離されたViewを超えてブレンドされないようにすることができます。

mixBlendMode値
  • normal: 要素はブレンドされずに背景の上に描画されます。
  • multiply: ソースカラーがデスティネーションカラーと乗算され、デスティネーションを置き換えます。
  • screen: 背景とソースカラー値の補数を乗算し、結果の補数を取ります。
  • overlay: 背景カラー値に応じて色を乗算またはスクリーンします。
  • darken: 背景とソースカラーのうち、より暗い方を選択します。
  • lighten: 背景とソースカラーのうち、より明るい方を選択します。
  • color-dodge: 背景色を明るくして、ソース色を反映させます。黒で描画しても変化はありません。
  • color-burn: 背景色を暗くして、ソース色を反映させます。白で描画しても変化はありません。
  • hard-light: ソースカラー値に応じて色を乗算またはスクリーンします。背景に強いスポットライトを当てたような効果です。
  • soft-light: ソースカラー値に応じて色を暗くしたり明るくしたりします。背景に拡散したスポットライトを当てたような効果です。
  • difference: 2つの構成色の中で明るい色から暗い色を減算します。
  • exclusion: 差分モードに似た効果を生み出しますが、コントラストが低くなります。
  • hue: ソースカラーのヒューと背景カラーの彩度と輝度を持つ色を作成します。
  • saturation: ソースカラーの彩度と背景カラーのヒューと輝度を持つ色を作成します。
  • color: ソースカラーのヒューと彩度、および背景カラーの輝度を持つ色を作成します。これにより、背景のグレースケールが保持され、モノクロ画像を色付けしたり、カラー画像に色調を与えたりするのに便利です。
  • luminosity: ソースカラーの輝度と背景カラーのヒューと彩度を持つ色を作成します。これにより、カラーモードとは逆の効果が得られます。

blend mode

アウトラインプロパティ

outlineWidthoutlineStyleoutlineSpreadoutlineColorも導入しました。これらのアウトラインプロパティは、それぞれのborderプロパティと非常によく似ていますが、パディングボックスの周りではなく、ボーダーボックスの周りにレンダリングされます。これらのプロパティにより、レイアウトに影響を与えることなく、要素のアウトラインを描画することで要素を強調表示できます。

詳細については、MDNドキュメントをご覧ください。

outline props

Androidバージョン15サポート & 16KBページサポート

Android 15での強制的なエッジツーエッジ表示

以前のリリースでは、Android 15のサポートに関して一部作業を行いました。Android 15における顕著な変更点の1つは、targetSdk 35でアプリをビルドした場合に、エッジツーエッジ表示が強制されることです。

まだこの問題を見ていない場合は、この問題を無視するとアプリのUIが破損する可能性があるため、以前の推奨事項を参照して、どのように対処すべきかを確認してください。

注意

アプリでreact-native-safe-area-contextを使用している場合、このライブラリはすでに強制的なエッジツーエッジ表示を処理しています。

Androidの16KBページサイズ対応

Android 15では16KBメモリページサイズがサポートされ、アプリのパフォーマンス向上などが可能になりますが、これまでの4KBベースのアプリは将来のデバイスで互換性がなくなる可能性があります。これは現在、開発者が一部のデバイスでテストして、16KBページサイズがOSのデフォルトになることに備えるためのオプトイン機能です。

0.77リリースにより、React Nativeは16KBページサイズを完全にサポートする準備が整い、開発者はこれを使用して16KBデバイス向けアプリをテストおよびリリースできるようになります。

16KBサポートの詳細については、公式Android開発者サイトを参照してください。

コミュニティCLIとテンプレートの更新

コミュニティCLI: react-native init の非推奨化

このバージョンでは、React Native 0.75で導入されたreact-native initコマンドの非推奨化が完全に完了します。

念のためですが、react-native initコマンドはもう使用できません。代わりに次のいずれかを行う必要があります。

  • Expoなどのフレームワークを使用し、新しいプロジェクトを作成するための専用コマンドnpx create-expo-appを使用する
  • npx @react-native-community/cli initでコミュニティCLIを直接呼び出す

コミュニティCLI: Metroからの「iOS/Androidで実行」キーハンドラーの削除

このバージョンでは、Metroから「a」と「i」のキーボードショートカットを削除しました。これらのショートカットは、run-androidrun-iosコミュニティCLIコマンドを呼び出すために使用されていました。これらのキーボードショートカットは開発者エクスペリエンスを悪化させ、めったに使用されませんでした。さらに、フレームワークはターミナル出力を調整するのに適していると考えています。

この変更の詳細については、こちらの専用記事をご覧ください。

コミュニティテンプレート: iOSアプリのプログラミング言語としてのSwift

情報

Expoを使用しているプロジェクトは、この変更の影響を受けないはずです。

この変更により、3つのファイル(main.mAppDelegate.hAppDelegate.mm)を1つの新しいAppDelegate.swiftに置き換えることで、コミュニティテンプレートをスリム化できました。

これは技術的には破壊的変更です。アップグレードヘルパーでは、Objective-CからSwiftへの変更がこのように表示されます。

Swift Upgrade Helper

Swiftに移行する必要はありません。iOSコミュニティテンプレートのObjective-C++バリアントは引き続きサポートされています(ただし、RCTAppDependencyProviderを統合する必要があることに注意してください)。新しいプロジェクトはiOSアプリ言語としてSwiftを使用して生成されますが、必要に応じてObjective-Cに戻すことも常に可能です。

制限事項

アプリにC++で記述されたローカルモジュールがある場合、このガイドに示されているように、それらをSwiftで登録することはできません。

アプリがこのカテゴリに該当する場合は、AppDelegateのSwiftへの移行をスキップし、アプリでObjective-C++を使い続けてください。

React Nativeのコアは、iOS、Android、その他のプラットフォーム間でのコード共有を促進するために、ほとんどC++を使用して開発されています。SwiftとC++の間の相互運用性は、まだ成熟しておらず安定していません。このギャップを埋め、Swiftにも移行できるようにする方法を検討しています。

RCTAppDependencyProvider

React Native 0.77では、アプリがサードパーティの依存関係をロードする方法がわずかに変更されています。これはコミュニティテンプレートの新しい行であり、見落とすとランタイムの問題を引き起こす可能性があります。必ずアプリに追加してください。

同等のObjective-Cの行は次のとおりです。

AppDelegate.mm
#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"<Your app Name>";
self.dependencyProvider = [RCTAppDependencyProvider new];
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

// remaining of the AppDelegate

破壊的変更

Metroでのconsole.log()ストリーミングの削除

React Nativeのデバッグのあらゆる側面が信頼性をもって動作し、最新のブラウザツールの機能と一致することを望んでいます。この品質基準を満たすため、0.76で非推奨化されたMetro経由のログ転送は、0.77で削除されます。

この統合は、デバイス上のデバッグターゲットと通信するためのカスタムアプローチに依存していました。この変更により、私たちはChrome DevTools Protocol (CDP)にのみ移行します。

  • JSログを表示するには、React Native DevToolsとその充実したコンソールパネルを使用してください。このパネルは、ログフィルタリング、豊富なオブジェクト検査、ライブ式などをサポートしています。
  • また、Expo ToolsRadon IDEなどのサードパーティ製拡張機能を使用して、VS CodeをCDPデバッガーとして接続することもできます。
    • これらの統合は、Reactチームによって直接サポートされているわけではありませんのでご注意ください。しかし、2025年にはファーストパーティのVS Codeサポートに取り組んでいます。
  • ExpoはExpo CLIでログストリーミングを提供し続けています。

詳細については、JavaScriptログがMetroから離れるのはなぜですか?を参照してください。

その他の破壊的変更

全般

  • アニメーション
    • ネイティブのループアニメーションは、ループが終了するたびにReactの状態更新を送信しません。
  • レイアウト
    • ScrollView上の固定ヘッダーのpositionが考慮されるようになりました。
    • 絶対位置指定の動作がより準拠するようになりました
  • JSモジュール
    • ReactFabricInternalsモジュールを削除
      • これはもうアクセスできません
  • ネイティブモジュール
    • NativeModulesオブジェクトを使用して、JSでターボモジュールをロードできるようになりました。
      • これにより、ネイティブモジュールとターボネイティブモジュールの互換性が向上します。
  • パッケージ
    • dev-middleware: フレームワークはミドルウェアホストに対するserverBaseUrlを指定する必要があります
  • APIの変更
    • AppRegistryからuseConcurrentRootの型を削除しました。これはすでに無視されていたためです。
    • NativeMethods TypeScript定義からrefsプロパティを削除しました。
  • UXの変更
    • 開発サーバーのキーコマンドから「iOSで実行」と「Androidで実行」を削除しました。

Android

  • Kotlin
    • これは、Kotlin 2.0.21に対してビルドされるReact Nativeの最初のバージョンです。Kotlin 2.0での変更点については、言語リリースノートで詳しく読むことができます。
  • APIの変更
    • ヌラビリティ
      • ReadableArray内の非プリミティブゲッターがオプションとして正しく型付けされるようになりました
      • ReactHost.createSurface()メソッドを非nullableにする
    • 名前の変更
      • DevSupportManagerBase.getCurrentContext()DevSupportManagerBase.getCurrentReactContext() に変更

さらに、いくつかのAPIが削除または可視性が制限されたため、アクセスできなくなりました。これらのAPIは内部のものであり、React Native開発者が直接必要とするものではありませんでした。完全なリストは以下のとおりです。

削除されたAndroid APIのリスト

以下のパッケージは現在内部化されており、アクセスできません。

  • com.facebook.react.views.progressbar
  • com.facebook.react.views.safeareaview
  • com.facebook.react.modules.accessibilityinfo
  • com.facebook.react.modules.appstate
  • com.facebook.react.modules.clipboard
  • com.facebook.react.modules.devmodule
  • com.facebook.react.modules.reactdevtoolssettings
  • com.facebook.react.views.unimplementedview

以下のクラスは現在内部化されているか、削除されているため、アクセスできません。

  • BackHandler.removeEventListener
  • BaseViewManagerInterface
  • BindingImpl
  • CompositeReactPackage
  • DebugOverlayTags
  • DefaultDevSupportManagerFactoryからのメソッドcreate()
  • DevToolsReactPerfLogger
  • FabricComponents
  • ImageStoreManager
  • InteropModuleRegistry
  • NativeModulePerfLogger
  • NoopPrinter
  • NotThreadSafeViewHierarchyUpdateDebugListener
  • OkHttpCallUtil
  • PrinterHolder
  • Printer
  • ReactDebugOverlayTags
  • ReactNativeFlipper
  • ReactViewBackgroundManager
  • ReactViewGroup.getBackgroundColor()
  • ReactVirtualTextShadowNode
  • ReactVirtualTextViewManager
  • SimpleSettableFuture
  • SwipeRefreshLayoutManager
  • TaskCompletionSource
  • DefaultReactHost.getDefaultReactHost()からのパラメータjsBundleLoader

iOS

  • APIの変更
    • 削除
      • RCTConstants.RCTGetMemoryPressureUnloadLevel
      • partialBatchDidFlush
      • RCTRuntimeExecutor
      • UseNativeViewConfigsInBridgelessMode
        • 適切な機能フラグに置き換えられました
      • UseTurboModuleInteropForAllTurboModules
        • TMsではInteropレイヤーが常に有効になっています。
    • 変更点
      • CGColorRefの使用をUIColorに置き換え
  • RCTAppDelegateは、サードパーティの依存関係をロードするためにRCTDependencyProviderを使用する必要があるようになりました。
  • CocoaPodsは、コンパイルの問題を避けるために、すべてのサードパーティの依存関係にC++バージョンを設定します。
React 19?

React 19は2024年12月6日にリリースされました。当時、React Native 0.77のブランチはすでにカットされており、React Native 0.77のRCを3つリリース済みでした。React Native 0.77のリリースでは、React 19を導入するには遅すぎました。

React 19はReact Native 0.78で提供される予定で、このバージョンのブランチはすでにカットされています。次のコマンドで新しいアプリを作成して試すことができます。

npx @react-native-community/cli init YourReact19App --version 0.78.0-rc.0

謝辞

React Native 0.77には、161人の貢献者による1061件を超えるコミットが含まれています。皆様の多大なご協力に感謝いたします!

このリリース投稿で機能のドキュメント作成に協力してくださった追加の著者の方々にも感謝します

  • Jakub Piasecki氏、display: contents機能への貢献に感謝します。
  • Nick GerlemanJoe VilchesJorge Cabiedes Acostaの各氏に、新しいスタイル機能のリリースに感謝します。
  • Alan Lee氏に、Android 16KBページサポートのコンテンツに感謝します。
  • Riccardo Cipolleschi氏とOskar Kwaśniewski氏に、テンプレートのSwiftへの移行をサポートしていただいたことに感謝します。
  • Nicola Corti氏に、react-native initの非推奨化サイクルコンテンツに感謝します。
  • Alex Hunt氏に、Metroからのconsole.logの削除に関するコンテンツに感謝します。

0.77へのアップグレード

既存のプロジェクトのReact Nativeバージョン間のコード変更を確認するには、アップグレードドキュメントに加えて、React Nativeアップグレードヘルパーを使用してください。

新しいプロジェクトを作成するには

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

Expoをご利用の場合、React Native 0.77はExpo SDK 52でサポートされます(Expoプロジェクト内でReact Nativeを0.77.0にアップデートする方法については、近い将来、別のExpoブログ記事で発表されます)。

情報

0.77がReact Nativeの最新の安定バージョンとなり、0.74.xはサポート対象外となります。詳細については、React Nativeのサポートポリシーをご覧ください。0.74の最終的なサポート終了アップデートを近い将来公開する予定です。