本日、React Native 0.78 をリリースできることをお知らせします!このリリースでは React Native 上での React 19 の導入に加え、Android Vector drawable のネイティブサポートや iOS の Brownfield 統合改善など、いくつかの重要な機能が含まれています。
ハイライト
- React 19
- より小さく高速なリリースに向けたプロセス変更
- Metro での JavaScript ログのオプトイン復活
- Android XML drawables のサポート追加
- iOS の ReactNativeFactory(Brownfield 統合の改善)
React 19
React 19 が React Native で使えるようになりました!React 19 への移行では React 18 からの変更点があるため、アプリの更新が必要です。例えば propTypes のような一部の API を削除しています。新しい React バージョンと互換させるためにアプリ側の調整を行ってください。段階的なアップグレード手順に従って移行してください。
移行後は、React の新機能(抜粋)を活用できます:
- Actions: async transitions を使う関数です。非同期の遷移が保留状態や楽観的更新、エラー処理などを自動で管理します。
- useActionState: Actions 上に構築されたユーティリティフック。関数を受け取り、呼び出せるラップされた Action を返します。呼び出されたときは Action の最後の結果とペンディング状態を返します。
- useOptimistic: 更新の最終状態を楽観的に表示するための新しいフック。非同期リクエスト中に最終状態を表示し、リクエストがエラーになった場合は自動で以前の値に戻ります。
- use: レンダー中にリソースへアクセスするための新しい API。Promise やコンテキストを読み取り、解決されるまで React がサスペンドします。
- ref as props: ref を他の prop と同じように渡せるようになりました。関数コンポーネントで
forwardRef が不要になり、コンポーネントの移行が容易になります。
その他多数の機能があります。利用可能な新機能の完全な一覧は React 19 のリリースブログを参照してください。
React Compiler
React Compiler は、メモ化を自動適用して React アプリケーションを最適化するビルド時ツールです。開発者は手動で useMemo、useCallback、React.memo などを使って不要な再計算を防げますが、忘れたり誤用したりすることがあります。React Compiler は JavaScript と React のルールを理解して、コンポーネントやフック内の値や値のグループを自動的にメモ化します。
今回のリリースでは、React Native アプリで React Compiler を有効にする手順を簡素化しました。以前はコンパイラ本体とランタイムの両方をインストールし、さらに Metro 経由で有効にするための Babel プラグインを設定する必要がありました。今回からはコンパイラ本体をインストールし、Babel プラグインを設定するだけでよくなりました。導入方法は段階的ガイドを参照してください。
コンパイラが動作しているか確認するには、React Native DevTools を開いてください。メモ化されたコンポーネントには Component Inspector に Memo ✨ タグが付与されます。
参考資料:
- React Compiler docs
- React Compiler Deep Dive
より小さく高速なリリースへ
2025 年に向けて、安定版の React Native リリースをより頻繁に出すためにリリースプロセスを更新します。破壊的変更の数を減らすことで、React Native のバージョンアップが簡単になります。リリースが早くなると内部で行われたバグ修正がより早くユーザーに届き、最新の機能を早く利用できるようになります。破壊的変更が少ないことで、エコシステム全体にとって安定したフレームワークになると考えています。
Metro における JavaScript ログのオプトイン
以前(0.77)に Community CLI ユーザー向けに削除していた Metro 開発サーバ経由の JavaScript ログストリーミングを、ユーザーのフィードバックと現状の代替案の検討を受けてオプトインで復活させました。オプトインするには新しい --client-logs フラグを使用します。npm スクリプトでエイリアス化しておくと便利です。
例:
npx @react-native-community/cli start
ログストリーミングは将来的に廃止される予定で、デフォルトは引き続きオフです。ただし、開発者が移行するための猶予期間を長めに設ける意図があります。この更新は 0.77.1 のマイナーリリースにも含まれます。
Android XML drawables のサポート追加
React Native 0.78 では、Android でアイコンやイラストなどのグラフィック要素を XML リソースとして読み込む新しい方法を提供します。これにより、ベクター画像を任意のスケールで品質を落とさず表示できる vector drawable や、より単純な装飾を描画する shape drawable を利用できます。これらは既存の Image コンポーネントでサポートされます。
今日からこの機能を使うには、静的リソースと同様に source prop で XML を参照してインポートします。XML リソースをビットマップの代わりに使うと、アプリサイズの削減や異なる DPI の画面での描画改善に寄与します。
例:
// require を使う場合
<Image source={require('./img/my_icon.xml')} style={{ width: 40, height: 40 }} />
// import を使う場合
import MyIcon from './img/my_icon.xml'
<Image source={MyIcon} style={{ width: 40, height: 40 }} />
パフォーマンスと品質
- 他の画像タイプと同様に、Android の XML リソースはメインスレッド外でロードおよびインフレートされるため、フレームドロップを引き起こしません。つまり、リソースが即時表示される保証はありませんが、ロード中にユーザー操作がブロックされることもありません。
- オフスレッドデコードは、多数のアイコンを同時にレンダリングする場合に特に重要です。内部アプリでは Android の vector drawable を使うことで大きなパフォーマンス改善が見られました。
- vector drawable は品質を落とさずに表示でき、画面密度ごとに別画像を含める必要がないため APK サイズの削減につながることがあります。読み込まれた後はメモリからコピーされるため、同じアイコンを複数回描画しても同時に表示されます。
トレードオフ
XML drawable リソースには制約があります:
- ビルド時に参照されている必要があります。これらのリソースは Android Asset Packaging Tool (AAPT) に渡され、生の XML をバイナリ XML に変換するビルドステップを通ります。Android は生の XML ファイルの読み込みをサポートしていない(known limitation)ため、Metro 経由でネットワーク越しにロードすることはできません。
- XML リソースのディレクトリ名やファイル名を変更した場合、Android アプリを再ビルドする必要があります。
- XML リソース自体にはサイズ情報がありません。デフォルトでは 0x0 になり、表示するには
width と height を指定する必要があります。
- 実行時に完全にカスタマイズできるわけではなく、寸法や全体の tint 色は制御できますが、リソース内の個々の要素属性(stroke width、border radius、色など)をランタイムで細かく変更することはできません。これらのカスタマイズには別バリアントの XML が必要です。
注: Android の vector drawable は react-native-svg の 1:1 の置き換えではありません。Android 向けに特化しており iOS では動作しません。プラットフォーム横断で同じ SVG を使いたい場合は引き続き react-native-svg を使用する必要があります。Vector drawable はカスタマイズ性を犠牲にしてパフォーマンス上の利点を提供します。
ReactNativeFactory(iOS)
React Native 0.78 では iOS 側の統合を改善しました。新しいクラス RCTReactNativeFactory が導入され、AppDelegate を必要とせずに React Native インスタンスを作成できるようになりました。これにより、たとえば ViewController 内で新しいバージョンの React Native を作成でき、Brownfield アプリとの統合が大幅に簡素化されます。
たとえば、アプリの View Controller に React Native のビューを表示したい場合、React Native 0.78 以降では(依存関係をインストールした後に)以下のようなコードを追加します:
import React
import React_RCTAppDelegate
public class ViewController {
var reactNativeFactory: RCTReactNativeFactory?
var reactNativeDelegate: ReactNativeDelegate?
public func viewDidLoad() {
super.viewDidLoad()
reactNativeDelegate = ReactNativeDelegate()
reactNativeFactory = RCTReactNativeFactory(delegate: reactNativeDelegate!)
view = reactNativeFactory?.rootViewFactory.view(withModuleName: "YourModuleName")
}
}
class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
override func sourceURL(for bridge: RCTBridge) -> URL? {
return self.bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}
上のコードは、RCTReactNativeFactory を作成しデリゲートを割り当て、React Native のルートビューを生成して View Controller に読み込む流れを示しています。デリゲートは sourceURL と bundleURL をオーバーライドして、読み込む JS バンドルの場所を React Native に教えます。
その他の破壊的変更
全般
- React Native DevTools
- FuseboxClient CDP ドメインの削除
- Codegen: コンポーネント配列型とコマンド配列型を分離
Android
- Nullability の変更: RootView を Kotlin に移行したことでパラメータ型が nullable から non-nullable に変更されました。
- 次のクラスは public から internal に移動、または削除され、もはやアクセスできません:
- com.facebook.react.bridge.GuardedResultAsyncTask
- com.facebook.react.uimanager.ComponentNameResolver
- com.facebook.react.uimanager.FabricViewStateManager
- com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageViewManager
iOS
- Image のロードイベントのサイズ情報を論理サイズからピクセルサイズに変更(旧アーキテクチャにのみ影響)
謝辞
React Native 0.78 には 87 人のコントリビューターによる 509 コミット以上が含まれています。皆さんのご尽力に感謝します!
このリリース記事のドキュメント作成に協力してくれた追加の著者にも感謝します:
- Dream11 team(React 19 機能の徹底テスト)
- Nicola Corti(Faster Releases に関する作業)
- Alex Hunt(Metro ログのオプトイン)
- Peter Abbondanzo(Android XML Drawable サポート)
- Oskar Kwaśniewski(ReactNativeFactory に関する作業)
0.78 へのアップグレード
既存プロジェクトの React Native バージョン間のコード差分を確認するには React Native Upgrade Helper と Upgrading docs を併用してください。
新しいプロジェクトを作成するには:
npx @react-native-community/cli@latest init MyProject --version latest
Expo を使用している場合、React Native 0.78 は Expo SDK の canary リリースでサポートされます。
注記: 0.78 は現在の最新安定版であり、0.75.x はサポート対象外に移行しました。詳細は React Native のサポートポリシーを参照してください。近く 0.75 の最終的な EoL 更新を公開する予定です。