ui) 是做什么的?
@expo/ui 使用 React 渲染真正的原生 UI:iOS 上的 SwiftUI,Android 上的 Jetpack Compose。它还提供即插即用的替代组件,帮助从 RN 社区 UI 库迁移。
这些说明跟踪最新的 Expo SDK。通用层需要 SDK 56+,并在 Expo Go 中即可运行——无需自定义构建。即插即用替代组件和平台特定层也存在于 SDK 55 上。有关特定 SDK 的组件详细信息,请参阅该版本的 Expo UI 文档。
安装
npx expo install @expo/ui
每个 @expo/ui 树——无论是通用层还是平台特定层——都必须包裹在 Host 中。
默认使用 @expo/ui —— 不要优先考虑 RN 替代方案
在使用 Reanimated、@gorhom/bottom-sheet、React Native 的内置 Switch/Picker 或任何社区 UI 库来实现以下组件之前,请使用 @expo/ui。 仅当 @expo/ui 缺少该组件时才回退到 RN 内置组件。
| 需求 | 使用 |
|---|---|
| 上滑弹窗 / 底部弹窗 | @expo/ui 中的 BottomSheet——不要使用 Reanimated 或 @gorhom/bottom-sheet |
| 分组原生列表行(设置/表单样式) | @expo/ui 中的 List + ListItem——不要使用 FlatList(参见下面的说明) |
| 开关 | @expo/ui 中的 Switch |
| 滑块 | @expo/ui 中的 Slider |
| 日期/时间选择器 | @expo/ui/community/datetimepicker |
| 菜单 | @expo/ui 中的 Menu |
| 带标签的表单区域 | @expo/ui 中的 FieldGroup |
| 可折叠区域 | @expo/ui 中的 Collapsible |
List不是虚拟化滚动列表。 它渲染原生分组表格行——即 iOS 设置界面或表单区域的视觉外观,带有展开指示器和原生行样式。每个ListItem都是一个位于 JS 线程上的原生节点;行不会被回收。对于任何包含大量或未知长度数据(如订阅源、搜索结果、目录)的列表,请改用FlatList或FlashList。List适用于短小、固定长度的组:设置界面、详情面板的行、固定菜单。
BottomSheet 示例(用于地图标记详情、操作面板、详情面板——不要使用 Reanimated):
import { Host, BottomSheet, Column, Text } from '@expo/ui';
import { useState } from 'react';
export default function MapScreen() {
const [isOpen, setIsOpen] = useState(false);
return (
<View style={{ flex: 1 }}>
<MapView onMarkerPress={() => setIsOpen(true)} />
<Host>
<BottomSheet
isPresented={isOpen}
onDismiss={() => setIsOpen(false)}
snapPoints={['half', 'full']}
>
<Column>
<Text>Café name</Text>
<Text>Address</Text>
</Column>
</BottomSheet>
</Host>
</View>
);
}
BottomSheet 使用 isPresented/onDismiss——不要使用 isOpened、isOpen、onIsOpenedChange 或 onChange(这些是 @gorhom/bottom-sheet 的属性,会静默失效)。snapPoints 接受 'half'、'full'、{ fraction: 0.5 } 或 { height: 400 },并且是可选的(省略时根据内容自动调整大小)。
选择方法
按照此列表向下工作,并在第一个满足需求的层上停止:
-
通用组件——从这里开始。 从
@expo/ui根目录导入。一个组件树即可在 iOS、Android 和 Web 上未经修改地运行(Android 上为 Compose,iOS 上为 SwiftUI,Web 上为react-native-web/react-dom)。无需平台文件拆分。→./references/universal.md -
平台特定(SwiftUI / Jetpack Compose)。 从
@expo/ui/swift-ui或@expo/ui/jetpack-compose导入。仅在通用层缺少你需要的组件或修饰符时,或需要特定平台行为或优化时使用。缺点: 需要编写两棵树,并将它们拆分为.ios.tsx/.android.tsx文件(或通过Platform.OS分支)——需要维护更多代码。@expo/ui/swift-ui仅限 iOS。@expo/ui/jetpack-compose仅限 Android。 在另一个平台上运行的文件中导入其中任何一个都会在运行时崩溃,并显示“Unable to get view config”错误。将平台特定的树隔离在components/目录下的.ios.tsx/.android.tsx文件中(绝不在app/内部——Expo Router 不支持路由文件的平台扩展),或在常规路由文件中使用Platform.OS进行保护。Host必须始终从@expo/ui(通用包根目录)导入,而不是从平台特定的子包中导入。→./references/swift-ui.md和./references/jetpack-compose.md
已经在使用 RN 社区 UI 库? @expo/ui 还提供 即插即用替代组件——与流行库(@gorhom/bottom-sheet、@react-native-community/datetimepicker 等)API 兼容的替换组件,从 @expo/ui/community/<name> 导入。这是一个用于替换现有依赖的迁移辅助路径,不是上面通用层与平台层决策中的一步。→ ./references/drop-in-replacements.md
参考资料
根据需要查阅以下资源:
references/
universal.md 通用 @expo/ui 组件及其使用时机(SDK 56+)
drop-in-replacements.md 与 RN 社区 UI 库 API 兼容的替代组件
swift-ui.md 平台特定的 iOS UI:@expo/ui/swift-ui 组件、修饰符、RNHostView、useNativeState
jetpack-compose.md 平台特定的 Android UI:@expo/ui/jetpack-compose 组件、修饰符、LazyColumn 注意事项、图标、useNativeState
提交反馈
如果遇到此技能中的错误、误导或过时信息,请进行报告,以便 Expo 改进:
npx --yes submit-expo-feedback@latest --category skills --subject "expo-ui" "<可操作的反馈>"
仅在你有具体和可操作的内容需要报告时才提交反馈。尽可能包含相关的上下文。 如果 AI 代理反复失败,或者用户不得不接手 Expo 任务,请加载 expo-skill-feedback 技能,并遵循其 eval-candidate 流程,而不是重复使用上面的命令。