Today we are excited to release React Native 0.77! このリリースには複数の機能が含まれます:display: contents、boxSizing、mixBlendMode、outline 関連プロパティなどの新しいスタイリング機能により、より強力なレイアウトオプションを提供します。また、最新のAndroidデバイスと互換性を持たせるために Android の16KBページサポートを導入しました。さらに、コミュニティテンプレートを Swift に移行して近代化するとともに、Objective-C を好む開発者向けに互換性とサポートを継続します。
ハイライト
- 新しい CSS 機能(レイアウト、サイズ指定、ブレンド向け)
- Android バージョン15サポート & 16KBページサポート
- Community CLI とテンプレートの更新
Breaking Changes
- Metro における console.log() のストリーミングの削除
新しい CSS 機能 — レイアウト、サイズ指定、ブレンドの改善
React Native 0.77 は Web と React Native の整合性をさらに進めます。アプリのレイアウト、サイズ指定、ブレンドをより細かく制御するための新しい CSS プロパティを追加しました。これらの変更は複雑なレイアウトの簡素化、テクスチャ追加、アクセシビリティ向上に役立ちます。
注意: これらの新機能はすべて New Architecture のみで利用可能です。
display: contents による簡素化されたレイアウト
display: contents は、要素自体をレイアウト構造から“消しつつ”その子要素は親の直下にあるかのようにレンダリングさせるプロパティです。ラッパーコンポーネントで子要素にスタイルを適用したいがレイアウトに影響を与えたくない場合や、イベントを扱うラッパーを作るとき、ShadowTree とやり取りする必要がある場合に有用です。
技術的には、display: contents は要素のレイアウトボックスを生成せずに子要素のレイアウトボックスは保持します。display: contents を設定した要素は事実上ビュー階層から平坦化されます。
例:ウィジェットが押されたときにアラートを表示したいケース。コンテナ内に赤い Widget がある状況から始めます。
function Container() {
return (
<View style={styles.container}>
<Widget />
</View>
);
}
次に、experimental な pointer events を使って、配下のコンポーネントが押されたときにユーザーにアラートを出す Alerting ラッパーを作ります。分かりやすくするためにこのコンポーネントの背景は青にしています。
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 が独自のレイアウトボックス(青い領域)を作るため、タップに反応する領域が想定より広くなってしまいます。Alerting の View に display: contents を設定すると、Alerting 自身のボックスを生成しなくなり、Widget からバブルしたポインターイベントのみを監視できるようになります。結果として元の Widget の境界内でのみアラートが発生します。
function Alerting({ children }) {
return (
<View style={{ display: 'contents' }} onPointerDown={() => alert('Hello World!')}>
{children}
</View>
);
}
boxSizing
boxSizing プロパティは、要素の各種サイズプロパティ(width、height、minWidth、minHeight など)がどのように計算されるかを定義します。boxSizing が border-box の場合、これらのサイズは要素のボーダーボックスに適用されます。content-box の場合はコンテンツボックスに適用されます。デフォルト値は border-box です。これは Web のデフォルトとは異なります。詳細を知りたい場合は Web のドキュメントを参照してください。
警告: border-box がこれまでのデフォルトであり、content-box を追加するまでは唯一の boxSizing 値でした。デフォルトを変更すると破壊的変更となり多くのレイアウトが突然壊れるため、後方互換性を保つ目的で border-box をデフォルトのままにしています。
例:どちらの View も padding: 20 と borderWidth: 10 を持つ場合、border-box ではボーダーとパディングをサイズ計算に含めますが、content-box ではコンテンツのみをサイズ計算に含めます。
mixBlendMode
mixBlendMode プロパティは、要素が同じスタッキングコンテキスト内の他の要素とどのように色をブレンドするかを制御します。各ブレンド関数の詳細は MDN documentation を参照してください。また、より細かくブレンド範囲を制御するために isolation プロパティも追加しました。
- isolation: isolate を View に設定すると、その View はスタッキングコンテキストを強制的に形成します。これにより、ある祖先 View に isolation を設定し、その内部で mixBlendMode を使う子要素が祖先の外にブレンドしないようにできます。
mixBlendMode の値(主要な説明を日本語で):
- normal: ブレンドせず背景の上に描画します。
- multiply: ソース色とデスティネーション色を乗算し、デスティネーションを置き換えます。
- screen: 背景とソース色の補色を乗算して結果を補色します。
- overlay: 背景色に応じて乗算またはスクリーンを適用します。
- darken: 背景とソースのうち暗い方を選択します。
- lighten: 背景とソースのうち明るい方を選択します。
- color-dodge: 背景色をソース色に合わせて明るくします。黒で描画すると変化はありません。
- color-burn: 背景色をソース色に合わせて暗くします。白で描画すると変化はありません。
- hard-light: ソース色に応じて乗算またはスクリーンを適用します。強いスポットライトを当てたような効果です。
- soft-light: ソース色に応じて暗くしたり明るくしたりします。拡散されたスポットライトのような効果です。
- difference: 2色のうち暗い方を明るい方から減算します。
- exclusion: Difference に似た効果を低コントラストで生成します。
- hue: ソース色の色相と、背景の彩度・明度で色を生成します。
- saturation: ソース色の彩度と、背景の色相・明度で色を生成します。
- color: ソース色の色相・彩度と、背景の明度で色を生成します(グレーレベルを保持し、単色画像の着色に便利)。
- luminosity: ソース色の明度と、背景の色相・彩度で色を生成します。Color モードとは逆の効果になります。
Outline プロパティ
outlineWidth、outlineStyle、outlineSpread、outlineColor を導入しました。これらは border 系プロパティと似ていますが、padding ボックスの周りではなく border ボックスの周りに描画されます。アウトラインを描画して要素をハイライトできますが、レイアウトには影響を与えません。詳細は MDN documentation を参照してください。
Android: バージョン15サポート & 16KBページサポート
Android 15 での強制 edge-to-edge
前リリースで Android 15 のサポートに向けた作業を既に行っています。Android 15 の目に見える変更の一つは、targetSdk 35 でアプリをビルドした場合に強制的に edge-to-edge 表示になる点です。まだ対応していない場合は、以前の推奨事項を確認してください。無視するとアプリの UI が壊れる可能性があります。
補足: react-native-safe-area-context を使用している場合、ライブラリ側で強制 edge-to-edge の処理を既に行っています。
Android の 16 KB ページサイズサポート
Android 15 は 16KB のメモリページサイズをサポートし、アプリのパフォーマンス向上を可能にしますが、従来の 4KB ベースのアプリは将来的なデバイスで互換性の問題が生じる可能性があります。現時点では開発者が特定デバイスでテストするためのオプトイン機能です。React Native 0.77 では 16 KB ページサイズをフルにサポートしており、開発者は 16 KB デバイス向けにテストおよびアプリの配布が可能になります。詳細は公式の Android Developers site を参照してください。
Community CLI とテンプレートの更新
Community CLI: react-native init の廃止完了
このバージョンで React Native 0.75 で導入された react-native init コマンドの廃止を完了します。つまり、react-native init コマンドは使用できなくなります。代わりに次のいずれかを使用してください:
- フレームワーク(例: Expo)を使う場合: npx create-expo-app
- Community CLI を直接呼ぶ: npx @react-native-community/cli init
Community CLI: Metro からの "run on iOS/Android" キーハンドラの削除
今回のリリースでは Metro から 'a' および 'i' のキーボードショートカットを削除しました。これらは run-android & run-ios の community CLI コマンドを呼び出すために使われていましたが、開発体験が悪く使用頻度も低かったため廃止しました。ターミナル出力の調整はフレームワーク側で行う方が適切だと考えています。詳しくはこの専用ポストを参照してください。
Community Template: iOS アプリのプログラミング言語を Swift に
補足: Expo を使っているプロジェクトはこの変更の影響を受けないはずです。
この変更により、コミュニティテンプレートをスリム化でき、main.m、AppDelegate.h、AppDelegate.mm の 3 ファイルを単一の新しい AppDelegate.swift に置き換えました。これは技術的には破壊的変更です。アップグレードヘルパーでは Objective-C から Swift への変更が表示されます。
Swift へ移行する必要はありません。iOS コミュニティテンプレートの Objective-C++ バリアントは引き続きサポートされます(ただし RCTAppDependencyProvider の統合は引き続き必要です)。新規プロジェクトはデフォルトで iOS の言語に Swift を使用して生成されますが、必要に応じて Objective-C に戻すこともできます。
制限事項
- アプリに C++ で書かれたローカルモジュールがある場合、Swift 上でそれらを登録できないことがあります(詳細は guide を参照)。該当する場合は AppDelegate の Swift への移行をスキップし、Objective-C++ を使い続けてください。
- React Native core は主に C++ で開発されており、iOS と Android 間でのコード共有を促進しています。Swift と C++ の相互運用性はまだ成熟しておらず安定していません。Swift への移行を可能にするための対応を検討中です。
RCTAppDependencyProvider
React Native 0.77 はサードパーティ依存関係の読み込み方法をわずかに変更しています。コミュニティテンプレートに入っている新しい行(RCTAppDependencyProvider)が抜けているとランタイムの問題になる可能性があります。アプリに必ず追加してください。Objective-C の等価コードは以下のとおりです。
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.moduleName = @"";
self.dependencyProvider = [RCTAppDependencyProvider new];
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
Breaking Changes
Metro における console.log() のストリーミングの削除
We want every aspect of React Native debugging to behave reliably and to match the functionality of modern