今日、React Native 0.75 をリリースできることを嬉しく思います!このリリースには、Yoga 3.1(% 値のサポート含む)や新アーキテクチャ向けの安定化修正、ユーザーに React Native フレームワークの使用を推奨する方針の導入など、いくつかの機能が含まれます。
ハイライト
- Yoga 3.1 とレイアウト改善
- 新アーキテクチャの安定化
- フレームワークの推奨(Using Frameworks)
- 破壊的変更の導入(下記参照)
Yoga 3.1 とレイアウト改善
前回 React Native 0.74 で Yoga 3.0 を出荷して以降、アプリのレイアウト能力に関して多くの改善を続けてきました。React Native 0.75 は Yoga 3.1 を同梱しており、公式の Yoga リリースブログポスト で詳細を確認できます。特に要望の多かった機能の一つが、ギャップや translate 情報などでの % 値サポートです。
これらの機能は新アーキテクチャでのみ利用可能です。利用を希望する場合は、新アーキテクチャへの移行を検討してください。
ギャップでのパーセント値
0.75 では gap、columnGap、rowGap props が % を含む文字列を受け取れるようになりました。例:
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)。
translate のパーセント値
transform prop の 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)。
新アーキテクチャの安定化
React Conf で新アーキテクチャがベータであると発表して以来、安定性向上のために多くのバグ修正と改善を行ってきました。目標は近い将来に新アーキテクチャを安定版と見なせる状態にすることです。そのため、旧アーキテクチャとの差分を埋めることに注力してきました。
修正・対応の例:
- Android での
adjustsFontSizeToFit の修正(#44075)
- Android で inline views と併用したときの
textAlign 動作修正(#44146)
- iOS でのテキストベースラインが上に移動してしまう問題の修正(#44932)
Expo の関係者と共同で、React Native Directory に新アーキテクチャのサポート情報を追加しました。これにより、ライブラリがすでに新アーキテクチャをサポートしているかどうかがすぐにわかるようになります。
また、新アーキテクチャに関するフィードバック収集のために New Architecture survey にご参加いただけるよう案内しています。さらに、New Architecture Working Group に投稿した「Supporting UIManager in the New Architecture」では、Android 上の UIManager API の概要と、より高度なアプリやライブラリの移行に役立つ点を解説しています。
このリリースでは、jsi::Runtime にアクセスするための推奨 API(blessed way)も追加しています。
TurboModules での jsi::Runtime へのアクセス
これまではネイティブモジュールから jsi::Runtime にアクセスする推奨方法がなく、利用者がフレームワークを迂回して危険な方法でアクセスすることがありました。0.74 で実験的 API を導入し、0.75 でこれらを安定化しました。
iOS
Turbo Native Module を RCTTurboModuleWithJSIBindings プロトコルに準拠させることで、installJSIBindingsWithRuntime を実装でき、スレッドセーフに runtime にアクセスできます。例:
@interface RCTSampleTurboModule() <RCTTurboModuleWithJSIBindings>
@end
#pragma mark - RCTTurboModuleWithJSIBindings
- (void)installJSIBindingsWithRuntime:(jsi::Runtime &)runtime {
runtime.global().setProperty(runtime, "myGlobalFunction", jsi::Function::createFromHostFunction(...));
}
Android
Turbo Native Module を TurboModuleWithJSIBindings インターフェースに準拠させ、JNI メソッド getBindingsInstaller を実装することで、C++ 側でスレッドセーフに runtime にアクセスできます。例:
public class SampleTurboModule extends NativeSampleTurboModuleSpec implements TurboModuleWithJSIBindings {
@Override
public native BindingsInstallerHolder getBindingsInstaller();
}
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(...));
});
}
CallInvoker API
UI スレッド上で runtime にアクセスする必要がある場合、CallInvoker という新 API を導入しました。単一メソッド invokeAsync を持ち、JS スレッドにジャンプして JS runtime を使った処理を安全に実行します。これらの API はフォワード互換性を持ちます。
iOS では RCTCallInvokerModule プロトコルに準拠させることで、モジュールは CallInvoker へアクセスできます。例:
@interface RCTSampleTurboModule() <RCTCallInvokerModule>
@end
[self.callInvoker callInvoker].invokeAsync([&](jsi::Runtime &runtime) {
});
Android では、CallInvoker は JNI ラッパーの CallInvokerHolder を介して ReactContext からアクセスできます。例:
public abstract CallInvokerHolder getJSCallInvokerHolder();
jsCallInvokerHolder->cthis()->getCallInvoker()->invokeAsync([&](jsi::Runtime &rt) {
});
フレームワークの使用(Using Frameworks)
今年の React Conf で共有したとおり、React Native アプリを構築する推奨方法は今やフレームワーク(例:Expo)を使うことです。詳細は以前のブログポスト「Use a framework to build React Native apps」を参照してください。
フレームワークの使用を推奨する方針を反映するため、今回のバージョンでは以下の変更を含みます:
/template フォルダを react-native パッケージから別リポジトリ(@react-native-community/template)へ移動しました。
react-native init コマンドは 2024-12-31 をもってサンセット予定です。
既に Expo のようなフレームワークを使用している場合、これらの変更による影響はありません。React Native 0.75 を Expo SDK 51 と共に使用できます(関連手順は専用の Expo ポストを参照してください)。
フレームワークを使っていない、または独自のフレームワークを構築している場合、以下の変更が影響します。
テンプレートを @react-native-community/template に移行
歴史的に、react-native パッケージ内に /template フォルダを同梱し、Community CLI が新規プロジェクトを作成する際に使われてきました。この構成ではテンプレートの更新が遅くなり、テンプレート変更ごとに新しい React Native リリースが必要でした。
フレームワーク利用を推奨する現在の方針に合わせ、コア NPM パッケージ内に意見の強いテンプレートを同梱することはビジョンに合わないため、テンプレートを @react-native-community/template に移動しました。これによりコミュニティがテンプレートを独立して保守・発展させやすくなり、React Native のリリースに依存せず更新できます。
この変更は Community CLI を使って新規プロジェクトを作成するユーザーにとっては透過的に動作します。テンプレートに関連する新規の issue はテンプレートの issue tracker に報告してください。upgrade-helper などテンプレートに依存する各種ツールも更新済みで、通常どおり動作します。
react-native init のサンセット
テンプレートと同様に、react-native init コマンドも新方針に合わせて扱いを変更します。歴史的に react-native init は新規プロジェクト作成のデフォルトコマンドでしたが、2024 年の時点でフレームワークが提供するオンボーディング体験と同等ではないと考えています。したがって、今後は react-native init の使用を推奨しません。代わりに Expo のようなフレームワークを使用してください。
現在でも Community CLI とテンプレートを使って react-native init で新規プロジェクトを作成できますが、以下の警告が表示されます:
Starting from December 31st 2024, the init command won’t create a project anymore. You will have to either:
- Use a framework such as Expo, with its own dedicate command to create a new project, such as `npx create-expo-app`
- Invoke the Community CLI directly with `npx @react-native-community/cli init`
react-native config と init 以外のコマンドは引き続き通常通り動作します。
注:円滑な移行体験を提供するため、react-native@0.75.0 パッケージはまだ @react-native-community/cli に依存していますが、近い将来この依存を削除する予定です。
オートリンク(auto-linking)性能改善
init コマンド更新作業の一環として、オートリンクロジックを書き直してパフォーマンスを向上させました。その結果、Android と iOS のビルド速度が改善されています。React Native 0.75 を使用する場合、Expo 利用時のオートリンクステップは Android で約 6.5x、iOS で約 1.5x 高速化する可能性があります。詳細はこちらをご参照ください。
破壊的変更(Breaking changes)
以下の破壊的変更は、主に高度な方法で React Native を使用している一部ユーザーに影響します。完全性と参照のためにここに列挙します。
- Touchables が TypeScript のジェネリック式で型として使えなくなりました
- minSdk 23 と minIOSVersion 13.4 をサポートする最後のバージョン
- Android:
JSIModule が削除されました
- Android: PopUp Menu がコアから削除されました
- iOS: プッシュ通知の非推奨作業を最終化しました
- Community CLI:
ram-bundle と profile-hermes コマンドの削除
Touchables に関する TypeScript の変更
TouchableOpacity と TouchableHighlight コンポーネントは関数コンポーネントに変換されました。そのため、これらを値と型の両方として同時に使うことはできません。例えば以下はもはや有効ではありません:
import { TouchableHighlight } from 'react-native';
const ref = useRef<TouchableHighlight>();
代わりに typeof TouchableHighlight や React.ComponentPropsWithRef<typeof TouchableHighlight> のような型表現を使用してください。
その他の注意点
- このリリースは、minSdk 23 および minIOSVersion 13.4 をサポートする最後のバージョンになります。将来のバージョンではこれらの下限が引き上げられる可能性があります。
- Android では
JSIModule が削除され、PopUp Menu はコアから除去されました。
- iOS 側ではプッシュ通知の非推奨化に関する作業を完了しています。
- Community CLI からは
ram-bundle と profile-hermes コマンドが削除されました。
本リリースの詳細や既知の問題、移行ガイド等は公式ドキュメントやリポジトリのリリースノートを参照してください。ご協力・フィードバックをお待ちしています。