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:
~58.0.1

一种用于在 Jetpack Compose 组件中渲染 React Native 视图时实现正确布局行为的组件。它通过更新 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 Content (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.

onLayout

Android
Optional • Type: (event: LayoutChangeEvent) => void

Called on mount and whenever this view's layout in the React Native view tree changes. With matchContents, the reported size is the one measured from the hosted view.

Inherited props

  • PrimitiveBaseProps