React,JetpackCompose,SwiftUIの比較
ページの目的
React,JetpackComposeでの開発をしてきたが、SwiftUIでの開発をする必要が出てきたでので、ReactやJetpackComposeと比較することでSwitUIでの実装のイメージをつける。
概要
React,JetpackCompose,SwiftUIの比較をAIに比較してもらった。
機能
機能 | React | Jetpack Compose | SwiftUI |
---|---|---|---|
使用言語 | JavaScript, TypeScript | Kotlin | Swift |
プラットフォーム | Web | Android | iOS, macOS, watchOS, tvOS |
宣言型UI | はい | はい | はい |
コンポーネントベース | はい | はい | はい |
状態管理 | useState, useReducer, Context API | remember, MutableState | @State, @Binding, @ObservedObject |
再利用可能なUIコンポーネント | はい | はい | はい |
レイアウトシステム | Flexbox | ConstraintLayout, Row, Column | VStack, HStack, ZStack |
ネイティブAPIアクセス | ライブラリ (React Native で可能) | 直接アクセス可能 | 直接アクセス可能 |
ホットリロード | はい (React Fast Refresh) | はい (Live Edit) | はい (Previews) |
コード共有 | WebとReact Native間で可能 | Android間で共有可能 | Appleエコシステム間で共有可能 |
UIのアニメーション | CSSまたはJavaScriptライブラリ | Modifierでサポート | .animation()でサポート |
カスタムジェスチャー対応 | ライブラリ(React Native Gestureなど) | ModifierとGestureDetectorでサポート | .gesture()でサポート |
マルチプラットフォーム対応 | はい (React Nativeでモバイル対応) | いいえ (Androidのみ) | はい (Apple製品全般) |
学習曲線 | 中程度 | 中程度 | やや高い |
コミュニティとエコシステム | 非常に大きい | 成長中 | 成長中 |
ライフサイクル
ライフサイクルイベント | React | Jetpack Compose | SwiftUI |
---|---|---|---|
初回マウント時 |
componentDidMount() (クラスコンポーネント) / useEffect(() => {...}, []) (関数コンポーネント) |
DisposableEffect { ... } で初回作成時に実行可能 |
.onAppear { ... } |
アンマウント時 |
componentWillUnmount() (クラスコンポーネント) / useEffect(() => {... return () => {...}}, []) (関数コンポーネント) |
DisposableEffect { onDispose { ... } } でアンマウント時に実行 |
.onDisappear { ... } |
更新時 (依存変数の変化) |
componentDidUpdate() (クラスコンポーネント) / useEffect(() => {...}, [dependencies]) (関数コンポーネント) |
LaunchedEffect(key) { ... } で特定の依存変数が変化した際に実行 |
特定のイベントに対応する必要あり |
副作用の処理 | useEffect() |
SideEffect { ... } または LaunchedEffect { ... }
|
@State , @Binding , @ObservedObject の変更に応じて動作 |
非同期処理 |
useEffect(() => { async function ... }, []) (async/await) |
LaunchedEffect でサポート (Coroutine) |
Task { ... } で非同期処理を実行 |
再レンダリングのトリガー |
useState , useReducer で状態変更 |
remember { mutableStateOf(...) } による状態管理 |
@State , @Binding , @ObservedObject による状態管理 |
クリーンアップ処理 |
useEffect(() => {... return () => {...}}, []) でクリーンアップ処理 |
DisposableEffect { onDispose { ... } } でクリーンアップ処理 |
.onDisappear { ... } でクリーンアップ処理 |
データバインディング
機能/特徴 | React | Jetpack Compose | SwiftUI |
---|---|---|---|
状態管理 (ローカル) | useState |
remember { mutableStateOf(...) } |
@State |
プロパティ変更による再描画 |
useState で状態が変わると再描画 |
mutableStateOf により状態が変わると再描画 |
@State プロパティが変更されると再描画 |
親から子へのデータバインディング | Props を使用 |
Modifier や Composable パラメータで渡す |
@Binding を使用して親の状態を共有 |
状態の監視と更新 (外部依存) |
useEffect または Context API を使用 |
StateFlow や LiveData を collectAsState で観測 |
@ObservedObject と @Published を使用 |
クラスベースの状態管理 | クラスコンポーネントで setState を使用 |
ViewModel クラスと LiveData / StateFlow
|
ObservableObject を使ったクラスで管理 |
状態の初期化と保持 |
useState または useReducer を使用 |
rememberSaveable を使用 |
@StateObject を使用 |
グローバルなデータの共有 | Context API を使用 |
CompositionLocal でデータを共有 |
@EnvironmentObject でデータを共有 |
UIの更新トリガー |
useState または setState による更新 |
MutableState の値変更に基づく |
プロパティラッパー (@State , @Binding 等) の値変更に基づく |
外部APIデータのバインディング |
useEffect で非同期処理とバインディング |
LaunchedEffect や StateFlow を活用 |
async/await で非同期処理 + @State にバインド |
カスタムイベントハンドリング | イベントハンドラ (onClick, onChange など) |
Modifier や LaunchedEffect を使用 |
.onAppear , .onDisappear などを使用 |
比較の概要
ローカル状態管理:
ReactではuseStateを使って状態を管理し、Jetpack ComposeではrememberとmutableStateOfを使用、SwiftUIでは@Stateを使ってローカルの状態を管理します。
親子間のデータバインディング:
Reactではpropsを使って親から子にデータを渡し、Jetpack ComposeではパラメータやModifierを使用、SwiftUIでは@Bindingを使って親から子に状態をバインドします。
状態の監視と更新:
ReactではuseEffectやContext APIで状態の監視と更新を行い、Jetpack ComposeではStateFlowやLiveDataを観測し、SwiftUIでは@ObservedObjectと@Publishedを使います。
グローバルデータ共有:
ReactではContext APIを使用してグローバルなデータを共有し、Jetpack ComposeではCompositionLocal、SwiftUIでは@EnvironmentObjectを使います。
外部APIデータのバインディング:
ReactではuseEffectを使って非同期処理とデータバインディングを行い、Jetpack ComposeではLaunchedEffectやStateFlow、SwiftUIではasync/awaitと@Stateを使います。
画面遷移
特徴/フレームワーク | React | Jetpack Compose | SwiftUI |
---|---|---|---|
画面遷移のライブラリ |
react-router-dom (主にWeb向け) |
NavHost , Composable 間の遷移 |
NavigationView と NavigationLink
|
遷移の宣言的な実装 |
<Link> 要素で実装 |
NavController とNavHost を使用 |
NavigationLink を使用 |
スタックベースの遷移管理 | React Router の useHistory やuseNavigate
|
NavHost でスタックベースの遷移管理 |
自動的にスタックベース |
パラメータの受け渡し | URL パラメータ (useParams )を利用 |
NavController の navigate にデータ渡す |
NavigationLink(destination:) で直接渡す |
戻る操作 (Back Navigation) |
useHistory フックを利用 |
popBackStack() で戻る遷移を実装 |
NavigationView で自動管理 |
アニメーションのサポート | アニメーションはカスタム実装 |
AnimatedVisibility , Transition でカスタマイズ |
matchedGeometryEffect でアニメーション可能 |
画面遷移後のデータ受け取り | URLクエリや状態管理 (Context APIなど) |
resultBack や Shared ViewModel を使用 |
@State や@Binding を使用 |
遷移ガード |
useEffect とルートガード |
popBackStack で条件付き遷移可能 |
onAppear , onDisappear でガード |
モーダル遷移 |
react-modal などのライブラリを利用 |
Dialog や BottomSheet を使用 |
sheet(isPresented:) を使用 |
多階層の遷移管理 | React Router の入れ子ルートで実現 | 複数のNavHost をネスト可能 |
NavigationLink をネスト可能 |
React:
react-router-domを使った宣言的なルーティングが一般的で、Webアプリ向けに最適化されています。useHistoryやuseNavigateでプログラム的に画面遷移を管理し、Linkを使った遷移が基本です。
画面遷移のアニメーションやモーダル表示は、カスタム実装や外部ライブラリに依存することが多いです。
Jetpack Compose:
Androidアプリでの画面遷移は、NavHostとNavControllerを使います。スタックベースのナビゲーション管理ができ、popBackStackで戻り操作を実装できます。
アニメーションや遷移後のデータ受け渡しに関しては、Jetpack Compose専用のコンポーネント(AnimatedVisibilityやSharedViewModel)を利用します。
SwiftUI:
NavigationViewとNavigationLinkを使った宣言的な画面遷移が可能で、簡潔なコードでスタックベースの遷移が自動的に管理されます。
モーダル遷移はsheet(isPresented:)を使って実装でき、画面遷移後のデータ受け渡しには@Stateや@Bindingなどが使われます。
Discussion