Host
A SwiftUI Host component that enables SwiftUI components in React Native.
A component that allows you to put the other @expo/ui/swift-ui components in React Native. It acts like <svg> for DOM, <Canvas> for react-native-skia, which underlying uses UIHostingController to render the SwiftUI views in UIKit.
Since the Host component is a React Native View, you can pass the style prop to it or matchContents prop to make the Host component match the contents' size.
Usage
Match contents sizing
Use matchContents to let the Host automatically size itself to fit its SwiftUI content, instead of requiring explicit dimensions.
Note:
matchContentsonly works correctly with components that have an intrinsic size or an explicitframe(for example,Button,Toggle,Text). Flexible-width components likeSliderand linearProgressViewexpand to fill available space and have no intrinsic width, usingmatchContentswith them will result in near-zero width. For those components, either apply aframemodifier on the component to give it an explicit width, or use explicit sizing withstyleon theHostinstead (for example,style={{ flex: 1 }}orstyle={{ width: 300 }}).
import { Button, Host } from '@expo/ui/swift-ui';
export default function MatchContentsExample() {
return (
<Host matchContents>
<Button
onPress={() => {
console.log('Pressed');
}}
label="Click"
/>
</Host>
);
}Note: Do not use
matchContentson the same axis as a scroll container (ScrollView,List,Form,LazyHStack,LazyVStack).matchContentsresolves to SwiftUI's.fixedSize, which sizes the scroll container to its content. It also leaves nothing past the viewport to scroll into, so scrolling silently stops working. UsematchContents={{ vertical: true }}together withstyle={{ width: '100%' }}(or any finite width on the scroll axis).
import { Host, HStack, ScrollView, Text } from '@expo/ui/swift-ui';
export default function ScrollViewMatchContents() {
return (
<Host
matchContents={{ vertical: true }}
style={{ width: '100%' }}>
<ScrollView axes="horizontal">
<HStack spacing={12}>
{Array.from({ length: 20 }).map((_, i) => (
<Text key={i}>Item {i}</Text>
))}
</HStack>
</ScrollView>
</Host>
);
}Explicit sizing with style
Use style to set explicit sizes on the Host, such as filling the available space with flex: 1.
import { Button, Host, VStack, Text } from '@expo/ui/swift-ui';
export default function ExplicitSizingExample() {
return (
<Host style={{ flex: 1 }}>
<VStack spacing={8}>
<Text>Hello, world!</Text>
<Button
onPress={() => {
console.log('Pressed');
}}
label="Click"
/>
</VStack>
</Host>
);
}Ignoring keyboard safe area
Use ignoreSafeArea="keyboard" when React Native is already handling keyboard avoidance (for example, with react-native-keyboard-controller), to prevent the SwiftUI host from applying its own keyboard inset.
import { Host, TextField } from '@expo/ui/swift-ui';
import {
KeyboardProvider,
KeyboardStickyView,
} from 'react-native-keyboard-controller';
import { View } from 'react-native';
export default function IgnoreKeyboardExample() {
return (
<KeyboardProvider>
<View style={{ flex: 1, backgroundColor: 'black' }}>
<KeyboardStickyView
style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
padding: 16,
backgroundColor: 'green',
}}>
<Host
matchContents
ignoreSafeArea="keyboard"
style={{ backgroundColor: 'red' }}>
<TextField placeholder="Enter text" axis="vertical" />
</Host>
</KeyboardStickyView>
</View>
</KeyboardProvider>
);
}Ignoring the container safe area
Use ignoreSafeArea="container" to remove only the container safe area (notch, home indicator, status and navigation bars). The keyboard safe area still applies.
import { Button, Host, HStack, Spacer } from '@expo/ui/swift-ui';
import { labelStyle } from '@expo/ui/swift-ui/modifiers';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function IgnoreContainerSafeAreaExample() {
const insets = useSafeAreaInsets();
return (
<Host
style={{ width: '100%', paddingTop: insets.top }}
matchContents={{ vertical: true }}
ignoreSafeArea="container">
<HStack>
<Button
systemImage="chevron.backward"
label="Back"
modifiers={[labelStyle('iconOnly')]}
/>
<Spacer />
<Button
systemImage="square.and.arrow.up"
label="Share"
modifiers={[labelStyle('iconOnly')]}
/>
</HStack>
</Host>
);
}Ignoring all safe areas
Use ignoreSafeArea="all" when you want SwiftUI content to extend behind the status bar and the keyboard, useful for full-screen overlays or backgrounds.
import { Host, Text, VStack } from '@expo/ui/swift-ui';
export default function IgnoreAllSafeAreasExample() {
return (
<Host
ignoreSafeArea="all"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}>
<VStack>
<Text>
This content extends behind the status bar and home
indicator.
</Text>
</VStack>
</Host>
);
}API
import { Host } from '@expo/ui/swift-ui';Component
Host
Type: React.Element<HostProps>
A hosting component for SwiftUI views.
HostProps
children
Type: ReactNode
colorScheme
Optional • Literal type: string
The color scheme of the host view.
Acceptable values are: 'light' | 'dark'
ignoreSafeArea
Optional • Literal type: string
Controls which safe area regions the SwiftUI hosting view should ignore.
'all'- ignores all safe area insets, including the keyboard.'container'- ignores only the container safe area (notch, home indicator, status and navigation bars). The keyboard safe area still applies.'keyboard'- ignores only the keyboard safe area.
Acceptable values are: 'container' | 'all' | 'keyboard'
layoutDirection
Optional • Literal type: string
The layout direction for the SwiftUI content. Defaults to the current locale direction from I18nManager.
Acceptable values are: 'leftToRight' | 'rightToLeft'
matchContents
Optional • Literal type: union • Default: false
When true, the host view will update its size in the React Native view tree to match the content's layout from SwiftUI. Can be only set once on mount.
Acceptable values are: boolean | { horizontal: boolean, vertical: boolean }
onLayoutContent
Optional • Type: (event: { nativeEvent: { height: number, width: number } }) => void
Callback function that is triggered when the SwiftUI content completes its layout. Provides the current dimensions of the content, which may change as the content updates.
pointerEvents
Optional • Literal type: string
Acceptable values are: 'auto' | 'box-none' | 'none' | 'box-only'
seedColor
Optional • Type: ColorValue
Seed color applied to the SwiftUI content as its tint. It propagates through the SwiftUI environment to theme interactive elements (buttons, switches, sliders, and similar controls) rendered by the children.
style
Optional • Type: StyleProp<ViewStyle>
useViewportSizeMeasurement
Optional • Type: boolean • Default: false
When true and no explicit size is provided, the host will use the viewport size as the proposed size for SwiftUI layout. This is particularly useful for SwiftUI views that need to fill their available space, such as Form.
Inherited props
Sources
The original Expo docs for this page:
- Host (SwiftUI) (
source-of-truth/versions/v57.0.0/sdk/ui/swift-ui/host.md) - Host (Universal) (
source-of-truth/versions/v57.0.0/sdk/ui/universal/host.md)