本日、React Native 0.74 をリリースしました!このリリースでは、Yoga 3.0、New Architecture 有効時のデフォルトでの Bridgeless、New Architecture におけるバッチ化された onLayout 更新、そして新規プロジェクトの既定パッケージマネージャとして Yarn 3 を導入しています。また、非推奨 API の削除(PropTypes の除去、PushNotificationIOS に対する破壊的変更)も行っています。Android では最小サポート SDK が 23(Android 6.0)に引き上げられています。
ハイライト
- Yoga 3.0
- New Architecture: Bridgeless をデフォルト化
- New Architecture: onLayout の更新がバッチ化
- 新規プロジェクトの既定パッケージマネージャに Yarn 3 を採用
主な変更点
Yoga 3.0
新しいレイアウト挙動
React Native 0.74 にはレイアウトエンジンの最新バージョンである Yoga 3.0 が含まれます。Yoga 3.0 はスタイルの予測可能性を向上させ、Web 向けに作られたコンポーネントをレンダリングする互換性をサポートします。注意している点として、実際のコンポーネントに大きな影響を与えるものについては、React Native は意図的にいくつかの誤ったレイアウト挙動を残しています。将来的なバージョンでより細かくレイアウト準拠を設定できるようにする予定です。
警告: 以前の React Native では row-reverse コンテナで margin / padding / border に関して left / right(および start / end)を反転していました。現在はこれらのプロパティの振る舞いが Web と一致します。これに依存していたコードは修正が必要になる場合があります。
例(スタイルの違い):
<View style={{ flexDirection: 'row', backgroundColor: 'red', margin: 10, width: 200, height: 100 }}>
<View style={{ flexDirection: 'row-reverse', backgroundColor: 'blue', flex: 1, marginLeft: 50 }}>
<View style={{ backgroundColor: 'green', height: '50%', flex: 1, marginLeft: 50 }} />
</View>
</View>
align-content: 'space-evenly' のサポート
Yoga 3.0 は alignContent: 'space-evenly' をサポートします。これはマルチラインの flex コンテナ内の行を、行間とコンテナ端との間に等間隔で分配します。
(参照: World Wide Web Consortium)
position: 'static' のサポート
情報: position: 'static' は New Architecture のみでサポートされています。
position: 'static' にマークされた要素はオフセットできず、絶対配置要素の含有ブロック判定に考慮されません。これにより、直近の親ではない先祖要素に対して相対的に要素を配置することが可能になります。
例:
<View style={{ backgroundColor: 'blue', width: 200, height: 200, flexDirection: 'row-reverse' }}>
<View style={{ backgroundColor: 'red', width: 100, height: 100, position: 'static' }}>
<View style={{ backgroundColor: 'green', width: 25, height: '25%', left: 25, top: 25, position: 'absolute' }} />
</View>
</View>
上記では緑色の要素は left と top を宣言しており、その基準は親ではなく青色の要素(先祖)になります。position が指定されない場合、React Native はデフォルトで position: 'relative' を用います。
New Architecture: Bridgeless をデフォルトに
このリリースでは、New Architecture が有効なときに Bridgeless モードをデフォルトにしました。Bridgeless をデフォルトにする移行については関連の投稿(this post)で詳しく説明しています。移行をスムーズにするために、Bridgeless をカバーする相互運用レイヤーを強化し、いくつかのライブラリと連携して初日から動作するように対応しました。
Bridgeless のみを改善したわけではなく、New Renderer の相互運用レイヤも改善しています。最もエキサイティングな点は、これらがデフォルトで有効になったことで、どのコンポーネントを通すかを指定する必要がなくなったことです(詳細は該当ページを参照)。New Architecture に関するドキュメントは react-native-new-architecture リポジトリにあります。New Architecture がデフォルトになった際には、これらの情報は reactnative.dev に統合されます。
New Architecture: onLayout の更新がバッチ化
onLayout コールバック内の state 更新はバッチ処理されるようになりました。以前は onLayout イベント内の各 state 更新が新しいレンダコミットを発生させていました。
例:
function MyComponent(props) {
const [state1, setState1] = useState(false);
const [state2, setState2] = useState(false);
return (
<View>
<View onLayout={() => { setState1(true); }}>
<View onLayout={() => {
// このイベントが実行された時点で state1 の新しい値はここからは観測できません。
setState2(true);
}}>
</View>
</View>
</View>
);
}
0.74 では setState1 と setState2 の更新はまとめてバッチされます。この変更は React の予期される挙動であり、再レンダ回数の減少をもたらします。
危険: この変更はバッチ化されていない state 更新に依存していたコードを壊す可能性があります。必要に応じて updater 関数や同等の手法にリファクタリングしてください。
新規プロジェクトの既定パッケージマネージャに Yarn 3 を採用
新規プロジェクトを React Native Community CLI で初期化する際の既定の JavaScript パッケージマネージャは Yarn 3 になりました。Yarn 3.x は nodeLinker: node-modules モードで使用され、React Native ライブラリとの互換性を提供します。これにより従来の Yarn Classic (1.x、非推奨) に代わります。既存アプリで Yarn バージョンをアップグレードする方法はこのガイドを参照してください。
例: ヘルプ表示
$ yarn --help
━━━ Yarn Package Manager - 3.6.4 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$ yarn command >
Community CLI は --pm フラグ経由で他のパッケージマネージャを指定してプロジェクトを初期化することもサポートしています(詳細はドキュメントを参照)。
破壊的変更
Android 最小 SDK 引き上げ(Android 6.0)
React Native 0.74 の最小 Android SDK 要件は 23(Android 6.0)になりました。これまでは Android 5.0(API 21)でした。この変更に関する背景は関連のコンテキストを参照してください。
ボーナス: Android アプリサイズの削減
最小 SDK 引き上げとネイティブビルドのいくつかの改善により、ユーザーデバイス上のアプリサイズを大幅に削減できました。例えば React Native 0.74 で新規作成したアプリはデバイス上で約 13% 小さくなり、約 4MB の節約になります。
非推奨の PropTypes の削除
0.74 以前、React Native は PropTypes を同梱していました(これは React 15.5(2017年)で非推奨になっている API です)。今回、React Native から組み込みの PropTypes をすべて削除し、バンドルサイズ(minified で約 26.4kB)とメモリ負荷を削減しました。削除された PropTypes のプロパティは次の通りです:
- Image.propTypes
- Text.propTypes
- TextInput.propTypes
- ColorPropType
- EdgeInsetsPropType
- PointPropType
- ViewPropTypes
(該当コミット参照)PropTypes に依存しているアプリやライブラリは、TypeScript のような型システムへの移行を強く推奨します。
PushNotificationIOS に対する API 変更(非推奨)
React Native 0.74 では非推奨になっている PushNotificationIOS ライブラリを削除するための準備を進めています。このリリースでの変更は古い iOS API への参照を削除することに焦点をあてています。PushNotificationIOS は Apple の User Notifications フレームワークへ移行され、新しい API を介して通知のスケジューリングや処理を提供します。次のリリース(0.75)でこのライブラリをコアから切り離し、@react-native-community/push-notification-ios へ移す予定です。まだ PushNotificationIOS に依存している場合は次のリリース前に移行してください。
API の変更点
-
RCTPushNotificationManager の didRegisterUserNotificationSettings: コールバックは no-op だったため削除されました。
-
以下のコールバックは非推奨となり 0.75 で削除予定です:
- (void)didReceiveLocalNotification:(UILocalNotification *)notification;
- (void)didReceiveRemoteNotification:(NSDictionary *)notification;
-
getInitialNotification() でアプリを起動させた通知を取得するには、明示的に RCTPushNotificationManager の initialNotification を設定する必要があります:
[RCTPushNotificationManager setInitialNotification:response.notification];
-
JS 側で Notification のプロパティが変更されました。alertAction と repeatInterval は非推奨で 0.75 で削除されます:
type Notification = {
...
// NEW: Seconds from now to display the notification.
fireIntervalSeconds?: ?number,
// CHANGED: Used only for scheduling notifications. Will be null when
// retrieving notifications using getScheduledLocalNotifications or
// getDeliveredNotifications.
soundName?: ?string,
// DEPRECATED: This was used for iOS's legacy UILocalNotification.
alertAction?: ?string,
// DEPRECATED: Use fireDate or fireIntervalSeconds instead.
repeatInterval?: ?string,
};
-
PushNotificationIOS.removeEventListener の handler パラメータは未使用となり削除されました。
iOS の移行手順(要点)
-
AppDelegate に UNUserNotificationCenterDelegate を実装する必要があります。これは通常 application:willFinishLaunchingWithOptions: か application:didFinishLaunchingWithOptions: の起動時に行います(詳細は Apple のドキュメント参照)。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES;
}
-
フォアグラウンド時に通知が到着したときに呼ばれる userNotificationCenter:willPresentNotification:withCompletionHandler: を実装します。completionHandler を使って通知をユーザーに表示するかどうかを決定し、RCTPushNotificationManager に通知します。
-
(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
// PushNotificationIOS 上で 'notification' と 'localNotification' イベントが発火します
[RCTPushNotificationManager didReceiveNotification:notification];
// 通知をユーザーに表示するかどうかを決定
completionHandler(UNNotificationPresentationOptionNone);
}
-
通知がタップされた際の処理は userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: を実装します。アプリが通知で起動した場合は setInitialNotification: を呼び、必要に応じて didReceiveNotification: を呼びます。
-
(void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {
// 通知でアプリが起動した場合の判定
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
// JS 側で getInitialNotification() で取得できるようにする
[RCTPushNotificationManager setInitialNotification:response.notification];
}
// PushNotificationIOS 上で 'notification' と 'localNotification' イベントが発火します
[RCTPushNotificationManager didReceiveNotification:response.notification];
completionHandler();
}
-
置き換え先のコールバックにロジックを移行したら、以下のメソッドは削除してください(あるいは使用しないでください):
- application:didReceiveLocalNotification: [deprecated]
- application:didReceiveRemoteNotification: [deprecated]
- application:didReceiveRemoteNotification:fetchCompletionHandler: [非推奨ではないが UNUserNotificationCenterDelegate 方法に置き換え可能]
また、application:didRegisterUserNotificationSettings: とそれに対応する RCTPushNotificationManager の didRegisterUserNotificationSettings: の使用は削除してください。
(参考実装: RNTester の AppDelegate.mm)
- JS 側の変更点
- alertAction への参照を削除してください。
- removeEventListener の呼び出しで渡していた handler 引数は使用されなくなったため削除してください。
本リリースは多数の改良と破壊的変更を含んでいます。各項目について詳しい移行手順や追加のドキュメントが用意されているので、既存プロジェクトではリリースノートと移行ガイドを参照して準備を行ってください。