Expo UI with SwiftUI and Jetpack Compose in practice

Featuring
Kewin Wereszczyński
Software Engineer
@
Callstack
Łukasz Chludziński
Engineering Manager
@
Callstack
Luke Farrell
Senior Software Engineer
@
Callstack

Working with Expo UI in real projects

Expo UI introduces a new layer for building interfaces using SwiftUI on iOS and Jetpack Compose on Android. Instead of relying solely on shared React Native components, developers can now tap directly into platform-native UI systems.

In practice, this means wrapping native UI inside a host component and composing views using platform-specific primitives. SwiftUI relies on constructs like VStack and modifiers, while Jetpack Compose introduces its own layout and styling patterns. The result is a more native feel, but also a shift in how components are structured and maintained.

Setup friction and current limitations

Getting started isn’t entirely frictionless. Running Expo UI requires a development build instead of Expo Go, along with proper prebuild steps and native configuration. Even small misconfigurations can block builds or cause linking issues.

There are also inconsistencies between platforms. Some components available in SwiftUI don’t yet have equivalents in Jetpack Compose, which creates gaps when aiming for feature parity. This becomes visible when experimenting with components like color pickers or advanced UI elements.

Rethinking component architecture

Expo UI changes assumptions around shared components. Instead of a single implementation across platforms, developers may need to maintain separate UI logic for iOS and Android while keeping a shared interface at a higher level.

This introduces tradeoffs. On one hand, it allows deeper integration with platform design systems. On the other, it increases complexity in code organization and consistency. The approach shifts from “write once” toward selective platform specialization where it matters.

Native capabilities vs custom implementations

Access to native components brings immediate benefits. Platform-provided UI elements are performant, well-tested, and familiar to users. They remove the need to build and maintain complex components in JavaScript.

At the same time, fully custom cross-platform components still have value. They ensure consistency and reduce duplication, especially when parity between platforms is required. Choosing between native and shared implementations becomes a strategic decision rather than a default.

What this means for React Native development

Expo UI highlights a broader direction: closer alignment with native platforms while keeping React Native as the orchestration layer. It encourages developers to understand SwiftUI and Jetpack Compose concepts, even when working primarily in JavaScript.

This also raises the bar for platform awareness. Differences in behavior, styling, and capabilities become more explicit, pushing teams to make more deliberate decisions about UX and architecture.

Watch the full stream and explore the discussion in detail.

Insights

Learn more about Expo

cover

Dec 9Podcast

From Hobby Tool to Default: Expo's Journey and the New App Awards

Jon Samp (Expo) discusses the framework's evolution since becoming the React Native default, the death of the "eject" mentality, and the launch of the Expo App Awards.

cover

Aug 5Webinar

How to Gradually Migrate From React Native Community CLI to Expo

Learn how to migrate your React Native Community CLI app to Expo incrementally, with minimal risk. A recording of a webinar hosted by Callstack & Expo.

cover

Jan 2Podcast

Universal React Native Apps with DOM & React Server Components

Tune in to discussion with Evan Bacon, Expo Router's creator, about how DOM and React Server Components make creating React Native universal apps a breeze.

cover

Oct 11Podcast

Improving Developer Experience With Expo

In this episode, we dive into Expo's potential to reshape the future of React Native development and enhance the developer experience. Our guests are Jon Samp, Head of Product at Expo, and Cedric van Putten, a Software Engineer at Expo. Tune in to learn how Expo can help you build React Native apps faster and more efficiently.

cover

Jun 17Article

How to Make Mobile Payment in a React Native App With Stripe and Expo in 15 Minutes

Learn how to make your first React Native payment in a mobile app with Stripe and Expo. We provide a step-by-step guide.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.