SDK 55 の Expo UI:Jetpack Compose が React Native アプリで利用可能に
Product • React Native • Development • March 17, 2026 • 6 minutes read
著者: Kudo Chien (Engineering), Nishan Bende (Engineering), Aleksander Mikucki (Engineering)
Expo UI は SwiftUI と Jetpack Compose を React Native アプリに直接取り込みます。JavaScript でネイティブコンポーネントを再実装する代わりに、ネイティブの実装そのもの(同じコンポーネント、挙動、プラットフォームの仕上がり)を公開します。
SDK 54 で SwiftUI サポートと Jetpack Compose の早期アルファを導入して以降、開発者が実際にこれを使い、expo-widgets の基盤としても利用することで実運用での有用性を検証しました。しかし Jetpack Compose のサポートはアルファ段階で、完全なアプリでの検証はまだでした。SDK 55 ではこの点を改善しています。
重要なポイント
- Jetpack Compose は beta に昇格し、Material Design 3 のコンポーネントが十分そろっているため完全なアプリを構築できます。
- SwiftUI API は Apple の慣習に合わせて再設計され、既存のネイティブフレームワーク知識が直接活用できます。
なぜ重要か
Apple と Google は SwiftUI と Jetpack Compose に大きく投資を続けており、新しい API やコンポーネントはまずそちらに登場します。これらを JavaScript で追随して再実装するのは大変で追いつきにくいです。Expo UI は異なるアプローチを取ります:ネイティブフレームワークを直接公開することで、新機能が登場するとすぐに利用でき、API の表現が SwiftUI / Jetpack Compose の慣習に沿っているため、これらのフレームワークを知っている開発者(や AI)であれば新たに学ぶことなく Expo UI コードを書けます。
Jetpack Compose:alpha から beta へ
Compose API が実運用に耐えられるかを検証するため、Expo チームは WikiReader(@nsh07 のオリジナルのクローン)を Expo UI コンポーネントのみで構築しました。何が不足しているか、どこに粗さがあるかを見つけるためです。アプリでは Material Design 3 のコンポーネント(Card、LazyColumn、ListItem、DockedSearchBar、ModalBottomSheet など)を通して使用し、必要に応じて各コンポーネントを追加しました。各コンポーネントは実際の問題を解決することで採用されました。
以下は Expo UI と Jetpack Compose を使った設定画面の例です:
import { useState } from "react" ;
import { useColorScheme } from "react-native" ;
import { Host , Switch , Icon , ListItem , LazyColumn } from "@expo/ui/jetpack-compose" ;
import { clip , Shapes } from "@expo/ui/jetpack-compose/modifiers" ;
export default function SettingsScreen ( ) {
const colorScheme = useColorScheme ( ) ?? "light" ;
const [ wifi , setWifi ] = useState ( true ) ;
const [ bluetooth , setBluetooth ] = useState ( false ) ;
const [ darkMode , setDarkMode ] = useState ( false ) ;
return (
<Host style = { { flex : 1 } } colorScheme = { colorScheme } >
<LazyColumn verticalArrangement = { { spacedBy : 2 } } contentPadding = { { start : 16 , end : 16 , top : 8 , bottom : 16 } } >
<ListItem headline = "Wi-Fi" supportingText = "Connected" modifiers = { [ clip ( Shapes . RoundedCorner ( { topStart : 12 , topEnd : 12 } ) ) ] } >
<ListItem.Leading>
<Icon source = { require ( "../../assets/icons/wifi.xml" ) } tintColor = "#1d1b20" />
</ListItem.Leading>
<ListItem.Trailing>
<Switch value = { wifi } onValueChange = { setWifi } />
</ListItem.Trailing>
</ListItem>
<ListItem headline = "Bluetooth" supportingText = "Off" >
<ListItem.Leading>
<Icon source = { require ( "../../assets/icons/bluetooth.xml" ) } tintColor = "#1d1b20" />
</ListItem.Leading>
<ListItem.Trailing>
<Switch value = { bluetooth } onValueChange = { setBluetooth } />
</ListItem.Trailing>
</ListItem>
<ListItem headline = "Dark mode" modifiers = { [ clip ( Shapes . RoundedCorner ( { bottomStart : 12 , bottomEnd : 12 } ) ) ] } >
<ListItem.Leading>
<Icon source = { require ( "../../assets/icons/dark_mode.xml" ) } tintColor = "#1d1b20" />
</ListItem.Leading>
<ListItem.Trailing>
<Switch value = { darkMode } onValueChange = { setDarkMode } />
</ListItem.Trailing>
</ListItem>
</LazyColumn>
</Host>
) ;
}
Jetpack Compose を使ったことがある人なら、コンポーネント名と構造は馴染みがあるはずです — LazyColumn の配置とパディング、modifier チェーン、先頭と末尾のコンテンツを持つ ListItem。Compose ではこれらを composable ラムダパラメータとして渡しますが、Expo UI では React のコンパウンドコンポーネントパターン(ListItem.Leading, ListItem.Trailing)を使って同じレイアウトを JSX で表現します。
modifier システムも合わせました。Jetpack Compose 固有の modifier チェーンを JSX に持ち込み、@expo/ui の SwiftUI サイドと同じスタイルにしているため、両プラットフォームで modifier の挙動が一貫します:
<Box modifiers = { [ size ( 100 , 100 ) , background ( Color . android . dynamic . primaryContainer ) ] } >
<Text modifiers = { [ padding ( 16 ) ] } >
Hello from Compose
</Text>
</Box>
これにはスコープ化された modifier も含まれます:Row や Column には weight や matchParentSize といった Compose と同じ専用オプションがあります。modifiers の詳細はドキュメントを参照してください。
また、Icon コンポーネントを追加し、Material Symbols の XML ベクタードローブルをネイティブにレンダリングできるようにしました。Jetpack Compose の開発では Material Symbols を Android drawable XML として使うことが一般的です。アイコンは Material Symbols から Android drawable XML ファイルをダウンロードし、直接参照できます:
<Icon source = { require ( './path/to/symbol.xml' ) } />
個別の XML ファイルをダウンロードするのが手間に感じる場合、AI エージェントに生成させるのも手です。我々のケースでは AI が Expo UI 用のコードとアイコン XML ファイルの両方を生成してくれました。
Expo は全ての Material Design 3 コンポーネントをラップすることを目指しているわけではありません。WikiReader クローンで必要だったものを追加し、需要に応じて拡張していきます。これらのコンポーネント追加に協力してくれた外部コントリビューターに感謝します。
Learn more from @expo/ui/jetpack-compose documentation.
SwiftUI:より SwiftUI らしく
SDK 55 では、SwiftUI コンポーネントの名前付けと構造を SwiftUI 側と一致するように変更しました。DateTimePicker は DatePicker に、Switch は Toggle に、CircularProgress は ProgressView になりました。SwiftUI の経験があれば、コンポーネント名、modifier 名、全体構造が馴染みのあるものになるはずです。
Apple のドキュメントを参照すると Expo UI に直接マップされるため、変換レイヤーを学ぶ必要がなく、そのまま Apple のドキュメントを参照できます。AI ツールも既存のトレーニングデータから正しいコードを生成しやすくなります。
全ての SwiftUI view や modifier を網羅できるわけではないので、Expo UI は拡張可能にしています。カバーしていない部分は独自のカスタム SwiftUI view や modifier を作成して対応できます。hot-chocolate ショーケースアプリは SDK 55 と最新 API に更新済みで、SwiftUI を使った完全な例として参考になります。
Learn more from @expo/ui/swift-ui documentation.
AI と一緒に作る
ネイティブフレームワークに合わせる実用的な利点の一つは、AI と相性が良い点です。Expo UI が SwiftUI と Jetpack Compose の慣習に従っているため、AI ツールは既にこれらのパターンを深く理解しています。これを活用するために、expo/skills に Expo UI 固有のスキルを追加し、expo-mcp を使ったより密な統合を構築しました。
ワークフローは簡単です:スクリーンショットをアップロードするかやりたいことを記述すると、AI が SwiftUI と Jetpack Compose の両方で Expo UI コードを既存のパターンに従って生成します。今日試せるプロンプトの例:
Build an Android Settings-style screen using @expo/ui/jetpack-compose components (Column, Row, Switch, Slider) with Material Symbols for row icons, featuring grouped sections (Network, Display, Sound, Privacy) with toggle switches and a brightness slider.
今後の予定
我々は Expo UI において、SwiftUI と Jetpack Compose(将来的には web も含めて)の双方で動く共通コンポーネント API を目指して作業を進めています。しかし現時点では、SDK 55 を試してフィードバックをいただきたいです。@expo/ui/swift-ui や @expo/ui/jetpack-compose のどちら側でもいいので Expo UI を使ってアプリを作ってみてください。
- どのコンポーネントが足りないですか?
- 何が違和感ありますか?
皆さんのフィードバックが次に作るものを直接形作ります。