Choose native UI when platform fidelity is more important than identical cross-platform rendering. Expo UI exposes universal components backed by SwiftUI on iOS and Jetpack Compose on Android, with platform-specific escape hatches when a shared abstraction stops fitting.
Choose a Rendering Lane
- Use React Native components for highly branded, cross-platform surfaces.
- Use Expo UI universal components for settings, forms, lists, menus, controls, and other platform-shaped surfaces.
- Use platform files when the interaction is conceptually shared but its implementation should differ.
- Use direct SwiftUI or Jetpack Compose bindings for a platform-exclusive capability or modifier.
If a design requires continuously fighting a universal component's native behavior, it is probably in the wrong lane.
Adopt the Native Layout Model
Universal native trees live inside Host. Compose them with Column, Row, and Spacer, not React Native Flexbox assumptions. A Host can carry environment such as color scheme and Android seed color.
SwiftUI and Compose share useful concepts but not identical APIs:
| Intent | SwiftUI | Compose |
|---|---|---|
| Vertical composition | VStack | Column |
| Horizontal composition | HStack | Row |
| Layering | ZStack | Box |
| Transformation | modifier chain | modifier chain |
Modifier order can change layout, clipping, background, and interaction. Treat the chain as execution order, not a bag of CSS properties.
Use a Styling Escape Ladder
Start with the smallest mechanism that preserves the universal contract:
- Universal style props for basic dimensions and spacing.
- Text-specific styling for typography.
- Native modifiers for platform behavior and appearance.
.ios.tsxand.android.tsximplementations behind one typed interface.- A custom native view or module only when necessary.
Restart Metro after adding a new platform-specific file if resolution does not update.
Keep High-Frequency State Native
Text input selection, gesture progress, and other per-frame state should not round-trip through React state unless React must render from it. Native state and worklets can keep interaction responsive, then commit meaningful state at boundaries such as submit, blur, or gesture completion.
Do not create two competing sources of truth. Document which layer owns live state and when it synchronizes with application state.
Platform Quality Checklist
- Dynamic type and screen-reader labels work.
- Android uses Material 3 conventions where applicable.
- iOS and Android each have appropriate navigation and control behavior.
- Safe-area and keyboard behavior is tested inside the host.
- A shared abstraction does not erase meaningful platform differences.
Sources
Check the current Expo UI overview, universal components, and native state documentation because these APIs are evolving.