Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

RNHostView

一个允许在 Jetpack Compose 中嵌入 React Native 视图的组件。

Android
Included in Expo Go
Recommended version:
~57.0.18

一个组件,用于在 React Native 视图渲染于 Jetpack Compose 组件内部时实现正确的布局行为。它通过更新 shadow node 的大小,将 Jetpack Compose 的布局信息同步回 React Native 的 Yoga 布局系统。

当 React Native 视图放置在像 ModalBottomSheet、Card、Row、Column 等 Jetpack Compose 组件内部时,这些布局系统需要进行通信。RNHostView 连接了这两者之间的空白:

  • 使用 matchContents:shadow node 的大小会被设置为匹配子 React Native 视图的固有大小,从而允许 Jetpack Compose 父组件根据 React Native 内容来确定自身尺寸。
  • 不使用 matchContents:shadow node 的大小会被设置为匹配父 Jetpack Compose 视图的大小,从而允许 React Native 内容填充可用空间(适用于 flex: 1 布局)。

安装

Terminal
- npx expo install @expo/ui
- yarn expo install @expo/ui
- pnpm expo install @expo/ui
- bun expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

用法

使用 matchContents 的基础用法

当你希望 Jetpack Compose 的父容器根据 React Native 内容来决定自身尺寸时,请使用 matchContents。

RNHostViewCounterExample.tsx
import { useState } from 'react'; import { Pressable, Text as RNText } from 'react-native'; import { Host, Card, Column, Row, RNHostView, Text, } from '@expo/ui/jetpack-compose'; import { fillMaxWidth, padding, } from '@expo/ui/jetpack-compose/modifiers'; export default function RNHostViewCounterExample() { const [counter, setCounter] = useState(0); return ( <Host matchContents={{ vertical: true }} style={{ width: '100%' }}> <Card modifiers={[fillMaxWidth()]}> <Column verticalArrangement={{ spacedBy: 12 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>Mixing RN Components with Compose</Text> <Row horizontalArrangement={{ spacedBy: 24 }} verticalAlignment="center"> <RNHostView matchContents> <Pressable onPress={() => setCounter(prev => prev - 1)} style={{ height: 50, width: 50, borderRadius: 100, justifyContent: 'center', alignItems: 'center', backgroundColor: '#9B59B6', }}> <RNText style={{ color: 'white', fontSize: 24 }}> - </RNText> </Pressable> </RNHostView> <Text>{counter}</Text> <RNHostView matchContents> <Pressable onPress={() => setCounter(prev => prev + 1)} style={{ height: 50, width: 50, borderRadius: 100, justifyContent: 'center', alignItems: 'center', backgroundColor: '#9B59B6', }}> <RNText style={{ color: 'white', fontSize: 24 }}> + </RNText> </Pressable> </RNHostView> </Row> </Column> </Card> </Host> ); }

不使用 matchContents 的弹性内容

当你在 React Native 内容中使用 flex: 1 时,请省略 matchContents 属性,这样内容就会填充可用的 Jetpack Compose 空间。

RNHostViewFlexExample.tsx
import { View } from 'react-native'; import { Host, Card, Column, Row, RNHostView, Text, } from '@expo/ui/jetpack-compose'; import { fillMaxWidth, padding, size, } from '@expo/ui/jetpack-compose/modifiers'; export default function RNHostViewFlexExample() { return ( <Host matchContents={{ vertical: true }} style={{ width: '100%' }}> <Card modifiers={[fillMaxWidth()]}> <Column verticalArrangement={{ spacedBy: 12 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>RN components with flex: 1 children</Text> <Row horizontalArrangement={{ spacedBy: 20 }} modifiers={[size(100, 100)]}> <RNHostView> <View style={{ flex: 1, backgroundColor: '#9B59B6', borderRadius: 10, }} /> </RNHostView> </Row> </Column> </Card> </Host> ); }

在 ModalBottomSheet 中使用

RNHostView 在 ModalBottomSheet 中也能很好地工作,用于显示交互式 React Native 内容。

RNHostViewSheetExample.tsx
import { useRef, useState } from 'react'; import { Pressable, Text as RNText, View } from 'react-native'; import { Host, ModalBottomSheet, Button, Column, RNHostView, Text, useMaterialColors, } from '@expo/ui/jetpack-compose'; import type { ModalBottomSheetRef } from '@expo/ui/jetpack-compose'; import { padding } from '@expo/ui/jetpack-compose/modifiers'; export default function RNHostViewSheetExample() { const [visible, setVisible] = useState(false); const sheetRef = useRef<ModalBottomSheetRef>(null); const colors = useMaterialColors(); const hideSheet = async () => { await sheetRef.current?.hide(); setVisible(false); }; return ( <Host matchContents> <Button onClick={() => setVisible(true)}> <Text>Open sheet</Text> </Button> {visible && ( <ModalBottomSheet ref={sheetRef} onDismissRequest={() => setVisible(false)}> <Column verticalArrangement={{ spacedBy: 16 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>Mixing Compose + RN in a Bottom Sheet</Text> <RNHostView matchContents> <View> <RNText style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 8, color: colors.onSurface, }}> React Native Content </RNText> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, alignItems: 'center', }} onPress={hideSheet}> <RNText style={{ color: 'white', fontWeight: '600' }}> Close </RNText> </Pressable> </View> </RNHostView> </Column> </ModalBottomSheet> )} </Host> ); }

底部抽屉中的弹性 React Native 内容

使用不带 matchContents 的 RNHostView,让 React Native 视图填充抽屉内剩余的空间。配合父级 Column 上的 height 修饰符来控制抽屉尺寸。

RNHostViewFlexSheetExample.tsx
import { useRef, useState } from 'react'; import { Text as RNText, View } from 'react-native'; import { Host, ModalBottomSheet, Button, Column, RNHostView, Text, } from '@expo/ui/jetpack-compose'; import type { ModalBottomSheetRef } from '@expo/ui/jetpack-compose'; import { height, padding, } from '@expo/ui/jetpack-compose/modifiers'; export default function RNHostViewFlexSheetExample() { const [visible, setVisible] = useState(false); const sheetRef = useRef<ModalBottomSheetRef>(null); return ( <Host matchContents> <Button onClick={() => setVisible(true)}> <Text>Open flex content sheet</Text> </Button> {visible && ( <ModalBottomSheet ref={sheetRef} onDismissRequest={() => setVisible(false)} skipPartiallyExpanded> <Column modifiers={[height(400), padding(16, 16, 16, 16)]}> <RNHostView> <View style={{ flex: 1, backgroundColor: '#9B59B6', borderRadius: 10, }}> <RNText style={{ color: 'white', fontSize: 18, fontWeight: 'bold', padding: 16, }}> React Native 内容(flex: 1) </RNText> </View> </RNHostView> </Column> </ModalBottomSheet> )} </Host> ); }

API

import { RNHostView } from '@expo/ui/jetpack-compose';

Component

RNHostView

Android

Type: React.Element<RNHostProps>

RNHostViewProps

children

Android
Type: ReactElement

The RN View to be hosted.

matchContents

Android
Optional • Type: boolean • Default: false

When true, the RNHost will update its size in the Jetpack Compose view tree to match the children's size. When false, the RNHost will use the size of the parent Jetpack Compose View. Can be only set once on mount.

modifiers

Android
Optional • Type: ModifierConfig[]

Modifiers for the component.

style

Android
Optional • Type: StyleProp<ViewStyle>

Style applied to the host view's React Native shadow node. Useful for controlling its layout position (e.g. position: 'absolute') so the shadow layout matches where the hosting Compose component draws the content — important for measure()-based hit-testing such as Pressable.

Inherited props

  • PrimitiveBaseProps