👀

React NativeでSwiftUIやJetpack Composeを使う!Expo UIの基本と使いどころ

に公開

こんにちは!テラーノベルとテラードラマでiOS/Android/Webとフロントエンド周りを担当している @kazutoyoです!

今回は、React NativeからネイティブUIコンポーネントを直接利用できる @expo/ui ライブラリについて紹介します。

Expoが開発・メンテナンスをしているExpo UIは、Expo(React Native)からSwiftUIやJetpack Composeのコンポーネントを呼び出し、ネイティブのコンポーネントを表示することができるライブラリです。

https://docs.expo.dev/versions/latest/sdk/ui/

どんなコンポーネントがある?

Expo UIはiOS用(SwiftUI)とAndroid用(Jetpack Compose)で利用できるコンポーネントが異なります。
基本的には、ButtonやSwitch、TextFieldなど、それぞれのプラットフォームで提供されているプリミティブなコンポーネントをReact Native用にラップして提供しています。
https://docs.expo.dev/versions/latest/sdk/ui/swift-ui/
https://docs.expo.dev/versions/latest/sdk/ui/jetpack-compose/

y.azumaさんの記事でも詳細に説明されています。
https://zenn.dev/gemcook/articles/fa0a5831bccf90

どんなときに利用できる?

Expo UIは前述のとおり、iOS用とAndroid用でコンポーネントが分かれています。
つまり、同じボタンを表示する場合でも、iOSとAndroidで別々に実装する必要があります。

例えば、以下のようにiOSでは button.ios.tsx としてコンポーネントを作成します。

import { Button as ExpoUIButton, Host } from '@expo/ui/swift-ui';

export const Button = () => (
    <Host style={{ flex: 1 }}>
      <ExpoUIButton
        variant="default"
        onPress={() => {
          setEditingProfile(true);
        }}>
        Edit profile
      </ExpoUIButton>
    </Host>
)

同じようにAndroidでは button.android.tsx としてコンポーネントを作成します

import { Button as ExpoUIButton } from '@expo/ui/jetpack-compose';

export const Button = () => (
    <ExpoUIButton
      style={{ flex: 1 }}
      variant="default"
      onPress={() => {
        setEditingProfile(true);
      }}>
      Edit profile
    </ExpoUIButton>
)

このように、プラットフォームごとにUIを実装する必要があります。

「せっかくクロスプラットフォームで開発しているのに、それぞれ実装しないといけないなんて意味がないのでは?」と思うかもしれません。

実はその通りで、Expo UIはReact Nativeで開発するすべてのUIを置き換えるために作られたものではありません。

Expoの開発者である Kudo(@kudochien)氏も以下のように使い分けを提案しています。

  • 基本的なUIの作成: React NativeのViewを使う
  • すべてのプラットフォームでピクセルパーフェクトなUIにしたい場合: react-native-skiaを使う
  • 3Dにしたい: react-native-webgpuを使う
  • Webのエコシステムを使いたい: Expo DOM Componentsを使う
  • プラットフォームのネイティブのルック&フィールが必要?: Expo UIを使う

https://x.com/kudochien/status/1978805681378807936

つまり、クロスプラットフォームで問題ない要素にはReact NativeのView(やサードパーティのUIライブラリ)を使い、デザインやパフォーマンスでネイティブのコンポーネントが必要な場合にExpo UIを利用するという使い分けが推奨されています。

特に、最近ではiOS 26でLiquid Glass(ガラスのような流体エフェクト)も登場し、アプリ内でこの効果を利用したUIを追加したい場合などに、Expo UIのプリミティブな要素を組み合わせることで実現できます。

より詳細にExpo UIでのアプリ構築について学びたい場合は、以下のドキュメントが参考になります。
https://docs.expo.dev/guides/expo-ui-swift-ui/

まとめ

Expo UIは、プラットフォームネイティブのプリミティブなコンポーネントをReact Nativeから利用できるようにするライブラリです。

TamaguiやReactNativePaperなどサードパーティのUIコンポーネントなどと組み合わせながら、アプリを構築するのがより効率的になります。

Expo UIの将来的なマイルストーンとして、iOS/Android/Webで共通のユニバーサルコンポーネントの作成も検討されている[1]ようです。
これが実現すれば、プラットフォームごとの実装も減り、さらに使いやすくなるかもしれませんね。

それでは良いReact Nativeライフを!

脚注
  1. https://docs.expo.dev/guides/expo-ui-swift-ui/#can-i-use-expouiswift-ui-on-android-or ↩︎

テラーノベル テックブログ

Discussion