Componentes Drop-In de Expo UI
Componentes universales vs superficies específicas de SwiftUI/Compose.
Busca en todas las páginas de la documentación
Componentes universales vs superficies específicas de SwiftUI/Compose.
@expo/ui te permite que las aplicaciones Expo rendereen UI nativa - SwiftUI en iOS, Jetpack Compose en Android - desde componentes React. Usa importaciones universales (Host, Column, Button) cuando una API debe funcionar en ambas plataformas; recurre a @expo/ui/swift-ui o @expo/ui/jetpack-compose cuando necesites modificadores específicos de plataforma, materiales o controles que no tengan equivalente multiplataforma.
Tarjeta de referencia rápida - lista para copiar y pegar.
npx create-expo-app@latest MyExpoUIApp --template blank-typescript
cd MyExpoUIApp
npx expo install @expo/ui// screens/SettingsNativeScreen.tsx
import { Host, Column, Row, Text, Switch, Button, Spacer } from "@expo/ui";
export default function SettingsNativeScreen() {
return (
<Host style={{ flex: 1 }}>
<Column spacing={16} padding={16}>
<Text style={{ fontSize: 28, fontWeight: "700" }}>Notificaciones</Text>
<Row spacing={12} alignment="center">
<Column style={{ flex: 1 }}>
<Text style={{ fontSize: 17, fontWeight: "600" }}>Alertas push</Text>
<Text style={{ fontSize: 14, opacity: 0.7 }}>Actualizaciones de pedidos y promociones</Text>
</Column>
<Switch defaultValue={true} label="Alertas push" />
</Row>
<Spacer />
<Button label="Guardar preferencias" variant="borderedProminent" onPress={() => {}} />
</Column>
</Host>
);
}// Mejora específica de plataforma (patrón de archivo solo iOS)
// components/GlassHeader.ios.tsx
import { Host, Text, VStack } from "@expo/ui/swift-ui";
import { background, glassEffect, padding } from "@expo/ui/swift-ui/modifiers";
export function GlassHeader({ title }: { title: string }) {
return (
<Host matchContents>
<VStack modifiers={[padding({ all: 16 }), glassEffect({ glass: { variant: "regular" } })]}>
<Text modifiers={[background("transparent")]}>{title}</Text>
</VStack>
</Host>
);
}// components/GlassHeader.tsx - fallback de Android
import { Text, View } from "react-native";
export function GlassHeader({ title }: { title: string }) {
return (
<View style={{ padding: 16, backgroundColor: "#f1f5f9" }}>
<Text style={{ fontSize: 22, fontWeight: "700" }}>{title}</Text>
</View>
);
}Cuándo recurrir a esto:
RNHostView.Pantalla de configuración híbrida: diseño universal, RNHostView para una isla de gráfico React Native, y encabezado de vidrio solo para iOS.
// screens/HybridDashboardScreen.tsx
import { Host, Column, Row, Text, Button, RNHostView } from "@expo/ui";
import { useColorScheme } from "react-native";
import { GlassHeader } from "../components/GlassHeader";
import { SpendingChart } from "../components/SpendingChart"; // componente RN estándar
export default function HybridDashboardScreen() {
const scheme = useColorScheme() ?? "light";
return (
<Host style={{ flex: 1, backgroundColor: scheme === "dark" ? "#0f172a" : "#f8fafc" }}>
<Column spacing={0} style={{ flex: 1 }}>
<GlassHeader title="Gastos" />
<Column spacing={16} padding={16} style={{ flex: 1 }}>
<Row spacing={8} alignment="center">
<Text style={{ fontSize: 15, opacity: 0.75 }}>Este mes</Text>
<Text style={{ fontSize: 28, fontWeight: "700" }}>$1,284.00</Text>
</Row>
{/* Isla de RN dentro del diseño nativo */}
<Host style={{ flex: 1, minHeight: 220, borderRadius: 12, overflow: "hidden" }}>
<RNHostView style={{ flex: 1 }}>
<SpendingChart />
</RNHostView>
</Host>
<Button
label="Ver transacciones"
variant="bordered"
onPress={() => {}}
accessibilityLabel="Ver transacciones"
/>
</Column>
</Column>
</Host>
);
}// components/SpendingChart.tsx - React Native ordinario
import { View, Text, StyleSheet } from "react-native";
const BARS = [40, 65, 30, 80, 55];
export function SpendingChart() {
return (
<View style={styles.chart}>
{BARS.map((h, i) => (
<View key={i} style={[styles.bar, { height: h }]} />
))}
<Text style={styles.caption}>Gráfico de RN dentro de RNHostView</Text>
</View>
);
}
const styles = StyleSheet.create({
chart: { flex: 1, flexDirection: "row", alignItems: "flex-end", gap: 8, padding: 16, backgroundColor: "#fff" },
bar: { flex: 1, backgroundColor: "#2563eb", borderRadius: 4 },
caption: { position: "absolute", bottom: 8, left: 16, fontSize: 12, color: "#64748b" },
});Lo que esto demuestra:
Host root de cada árbol @expo/ui - los diseños universales no funcionan sin él.Column / Row usan diseños de stack nativos con props spacing y alignment en lugar de objetos de estilo flexbox.Button / Switch de @expo/ui son controles nativos, no wrappers de Pressable.RNHostView incrusta componentes RN existentes dentro del chrome nativo - ruta de migración para sistemas de diseño híbridos..ios.tsx para APIs solo de SwiftUI (glassEffect) con fallback de RN en Android.@expo/ui conecta props de React a vistas SwiftUI / Compose via Expo Modules - el renderizado sucede en el thread de UI nativa donde sea compatible.@expo/ui) eligen la implementación de plataforma en tiempo de compilación - un árbol de componentes, dos backends nativos.*.ios.tsx / *.android.tsx.RNHostView crea una raíz RN anidada dentro de un diseño nativo - distinto de embebimiento brownfield de pantalla completa; ver RNHostView & Native UI Embedding.style limitados; superficies SwiftUI prefieren modificadores de @expo/ui/swift-ui/modifiers.| Importación | Renderiza | Usar para |
|---|---|---|
@expo/ui (Host, Column, Button) | SwiftUI + Compose | Chrome nativo multiplataforma |
@expo/ui/swift-ui | Solo SwiftUI | Glass, materiales, diseños de widgets |
@expo/ui/jetpack-compose | Solo Compose | Widgets Material de Android |
react-native (View, Pressable) | Diseño RN | DS personalizado, listas, Skia, pantallas heredadas |
import { Text, VStack } from "@expo/ui/swift-ui";
import { font, foregroundStyle, padding } from "@expo/ui/swift-ui/modifiers";
<Text
modifiers={[
font({ weight: "semibold", size: 17 }),
foregroundStyle("#111111"),
padding({ horizontal: 16 }),
]}
>
Hello
</Text>Los modificadores no son style de RN - se mapean a cadenas de modificadores de SwiftUI. Las extensiones de widgets usan el mismo vocabulario - ver App Extensions & Widgets.
| Capa | Herramienta |
|---|---|
| Chrome nativo (barra de herramientas, toggles) | @expo/ui |
| Listas y formularios densos | RN + Paper / Tamagui / NativeWind |
| Tokens de marca | Tu módulo de token - ver Design Systems Basics |
| Sabores de etiqueta blanca | Configuración de tema - ver Theming & Brand Flavors |
Falta el wrapper Host - Los hijos del layout fallan al montarse. Fix: Cada pantalla @expo/ui comienza con <Host>.
Usar <View> dentro de archivos de widgets SwiftUI - Los objetivos de widgets rechazan primitivas de RN. Fix: Solo @expo/ui/swift-ui en bundles de extensión.
Esperando píxeles idénticos en iOS y Android - Los componentes universales se mapean a idiomas de plataforma; el espaciado puede diferir. Fix: Diseña para roles, no paridad de píxeles.
RNHostView sin altura limitada - La isla del gráfico se colapsa a cero. Fix: Establece minHeight o flex: 1 en el wrapper Host.
Importar modificadores SwiftUI en Android - Fallo de compilación. Fix: Archivos específicos de plataforma o solo componentes universales.
Reemplazar la aplicación completa con @expo/ui - Listas, navegación y librerías RN de terceros aún necesitan diseño RN. Fix: Chrome nativo de drop-in selectivamente, no reemplazo wholesale.
| Alternativa | Usar Cuándo | No Usar Cuándo |
|---|---|---|
| @expo/ui universal | Switches nativos, botones, pantallas híbridas | Cada pantalla es una lista virtualizada compleja |
| @expo/ui/swift-ui | Materiales de iOS, widgets, Live Activities | Aplicación solo de Android |
| React Native Paper | Material Design en vistas RN | Necesitas widgets verdaderos de Compose |
| Tamagui / NativeWind | DS personalizado de marca en árbol RN | Efecto de vidrio y toggle nativo de plataforma |
| Vistas TurboModule personalizado | Control nativo a medida no en @expo/ui | @expo/ui ya distribuye el primitivo |
Sí para componentes universales y prototipos de RNHostView. Las extensiones de widgets y algunos objetivos solo de plataforma requieren expo prebuild y dev builds.
El contenedor raíz que conecta hijos de React a jerarquías SwiftUI/Compose nativas. Envuelve cada árbol de diseño de @expo/ui con <Host>.
Cuando el chrome nativo (barra de herramientas, control segmentado) debe envolver pantallas RN existentes sin reescribirlas. Ver RNHostView & Native UI Embedding.
Los componentes universales aceptan props de estilo limitados. Prefiere props de layout (spacing, padding, alignment). Mantén StyleSheet para hijos de RNHostView.
Los modificadores se compilan en cadenas de SwiftUI (font, padding, glassEffect). No cascada como CSS. Usa archivos de plataforma cuando los modificadores no tienen equivalente de Android.
Paper renderiza Material en vistas RN. @expo/ui renderiza Compose/SwiftUI nativo. Puedes combinarlos - formularios de Paper bajo un encabezado nativo de @expo/ui.
Establece props label / accessibilityLabel donde sea expuesto. Prueba con VoiceOver y TalkBack - los controles nativos se comportan diferente de Pressable. Ver Accessibility Basics.
Versiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0, y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 19 jul 2026