expo-sdk
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExpo SDK
Expo SDK
Overview
概述
Expo SDK 54+ provides a managed React Native development environment with file-based routing (Expo Router), native module access, and streamlined build tooling. This skill covers app configuration, the root layout provider pattern, and key Expo/RN libraries.
Prerequisite: or Expo SDK 54+ in
npx create-expo-apppackage.jsonExpo SDK 54+ 提供了一个托管式React Native开发环境,支持基于文件的路由(Expo Router)、原生模块访问以及简化的构建工具链。本技能涵盖应用配置、根布局提供者模式,以及关键的Expo/RN库。
前置条件:使用创建项目,或中已包含Expo SDK 54+
npx create-expo-apppackage.jsonWorkflows
工作流程
Setting up a new Expo demo:
- Create project:
npx create-expo-app [demo-name] --template blank-typescript - Install core dependencies:
pnpm add expo-router expo-image expo-haptics react-native-reanimated react-native-gesture-handler react-native-safe-area-context @gorhom/bottom-sheet @shopify/flash-list lucide-react-native nativewind tailwindcss@3 - Configure NativeWind (see skill)
nativewind - Set up root layout with provider stack
- Configure with scheme, name, splash
app.json - Add route groups and screens
- Run: (Expo dev server)
pnpm start
Adding a new library:
- Install with pnpm:
pnpm add [library] - Check if Expo config plugin needed in
app.json - Rebuild dev client if native module added:
npx expo prebuild
搭建新的Expo演示项目:
- 创建项目:
npx create-expo-app [demo-name] --template blank-typescript - 安装核心依赖:
pnpm add expo-router expo-image expo-haptics react-native-reanimated react-native-gesture-handler react-native-safe-area-context @gorhom/bottom-sheet @shopify/flash-list lucide-react-native nativewind tailwindcss@3 - 配置NativeWind(参考相关技能)
nativewind - 设置带有提供者栈的根布局
- 在中配置scheme、名称、启动页
app.json - 添加路由组和页面
- 运行:(Expo开发服务器)
pnpm start
添加新库:
- 使用pnpm安装:
pnpm add [library] - 检查是否需要在中添加Expo配置插件
app.json - 如果添加了原生模块,重新构建开发客户端:
npx expo prebuild
Guidance
指南
app.json Configuration
app.json配置
Key fields for demo apps:
| Field | Purpose |
|---|---|
| Display name |
| URL-safe identifier |
| Deep link scheme (e.g., |
| |
| Splash screen configuration |
| iOS bundle ID |
| Android package name |
| Expo config plugins (e.g., |
演示项目的关键字段:
| 字段 | 用途 |
|---|---|
| 显示名称 |
| URL安全的标识符 |
| 深度链接协议(例如: |
| 屏幕方向(演示项目默认 |
| 启动屏配置 |
| iOS包标识符 |
| Android包名 |
| Expo配置插件(例如: |
Root Layout Provider Pattern
根布局提供者模式
The root wraps the entire app with providers. Standard order:
app/_layout.tsxGestureHandlerRootView (flex: 1)
└── SafeAreaProvider
└── ThemeProvider / Context
└── Stack (Expo Router)- must be outermost (required by gesture handler and bottom sheets)
GestureHandlerRootView - provides safe area insets to all descendants
SafeAreaProvider - App-level context providers go between SafeAreaProvider and Stack
- for custom headers
<Stack screenOptions={{ headerShown: false }} />
根目录下的会用提供者包裹整个应用。标准顺序:
app/_layout.tsxGestureHandlerRootView (flex: 1)
└── SafeAreaProvider
└── ThemeProvider / Context
└── Stack (Expo Router)- 必须是最外层(手势处理器和底部弹窗的要求)
GestureHandlerRootView - 为所有子组件提供安全区域内边距
SafeAreaProvider - 应用级别的上下文提供者应放在SafeAreaProvider和Stack之间
- 使用来自定义头部
<Stack screenOptions={{ headerShown: false }} />
expo-image (replaces RN Image)
expo-image(替代RN Image)
Use for all image rendering — provides caching, blurhash placeholders, content-fit modes, and animated transitions.
expo-imageKey props:
- — URI string or require() for local images
source - — blurhash string for loading state
placeholder - —
contentFit|'cover'|'contain''fill' - — fade-in duration in ms (e.g.,
transition)300
所有图片渲染都使用——它提供缓存、blurhash占位符、内容适配模式以及动画过渡效果。
expo-image关键属性:
- —— URI字符串或本地图片的require()引用
source - —— 加载状态下的blurhash字符串
placeholder - ——
contentFit|'cover'|'contain''fill' - —— 淡入动画时长(单位:毫秒,例如
transition)300
expo-haptics
expo-haptics
Provide tactile feedback on interactions:
- — light tap for selections, toggles
Haptics.selectionAsync() - — button press, card tap
Haptics.impactAsync(ImpactFeedbackStyle.Medium) - — action completion
Haptics.notificationAsync(NotificationFeedbackType.Success)
Use sparingly — haptics on every touch is annoying.
为交互提供触觉反馈:
- —— 轻触反馈,适用于选择、切换操作
Haptics.selectionAsync() - —— 按钮按压、卡片点击时的反馈
Haptics.impactAsync(ImpactFeedbackStyle.Medium) - —— 操作完成时的反馈
Haptics.notificationAsync(NotificationFeedbackType.Success)
注意适度使用——每次触摸都触发触觉反馈会很烦人。
Safe Area Insets
安全区域内边距
Account for device notch, status bar, and home indicator:
- — returns
useSafeAreaInsets()in points{ top, bottom, left, right } - Apply to screen containers:
paddingTop: insets.top - NativeWind classes: use or wrap in SafeAreaView
pt-[${insets.top}px]
适配设备的刘海、状态栏和Home指示器:
- —— 返回
useSafeAreaInsets()(单位:点){ top, bottom, left, right } - 应用到屏幕容器:
paddingTop: insets.top - NativeWind类:使用或包裹在SafeAreaView中
pt-[${insets.top}px]
@gorhom/bottom-sheet
@gorhom/bottom-sheet
Replaces Radix Dialog for mobile modal patterns:
- Use for detail views, selections, filters, forms
- Define snap points:
snapPoints={['25%', '50%', '90%']} - Backdrop: with press-to-dismiss
backdropComponent - for scrollable content inside sheets
BottomSheetScrollView - Requires as ancestor
GestureHandlerRootView
替代Radix Dialog的移动端模态框方案:
- 适用于详情页、选择器、筛选器、表单
- 定义吸附点:
snapPoints={['25%', '50%', '90%']} - 背景层:使用实现点击关闭
backdropComponent - 用于弹窗内的可滚动内容
BottomSheetScrollView - 要求祖先组件包含
GestureHandlerRootView
FlashList (replaces FlatList)
FlashList(替代FlatList)
High-performance list rendering from :
@shopify/flash-list- Drop-in FlatList replacement with mandatory prop
estimatedItemSize - — estimated height of each item in points
estimatedItemSize={80} - Recycling architecture for smooth 60fps scrolling
- Use for NativeWind styling
contentContainerClassName
来自的高性能列表渲染组件:
@shopify/flash-list- 可直接替换FlatList,但必须传入属性
estimatedItemSize - —— 预估每个列表项的高度(单位:点)
estimatedItemSize={80} - 采用回收架构,实现60fps流畅滚动
- 使用进行NativeWind样式设置
contentContainerClassName
lucide-react-native
lucide-react-native
Icon library for React Native (matches web lucide-react):
- Import individual icons:
import { Home, Settings, ChevronRight } from 'lucide-react-native' - Props: ,
size,colorstrokeWidth - Consistent icon set across mobile and web codebases
React Native的图标库(与web端lucide-react保持一致):
- 导入单个图标:
import { Home, Settings, ChevronRight } from 'lucide-react-native' - 属性:、
size、colorstrokeWidth - 在移动端和web端代码库中使用统一的图标集
StatusBar
StatusBar
Configure status bar appearance per screen:
- for light backgrounds
<StatusBar style="dark" /> - for dark backgrounds
<StatusBar style="light" /> - Import from
expo-status-bar
为每个页面配置状态栏外观:
- 浅色背景下使用
<StatusBar style="dark" /> - 深色背景下使用
<StatusBar style="light" /> - 从导入
expo-status-bar
Best Practices
最佳实践
- Wrap root layout in with
GestureHandlerRootViewstyle={{ flex: 1 }} - Use expo-image for all images (caching, blurhash, performance)
- Add haptics to primary actions only (buttons, major selections) — not every touch
- Set on all FlashList components
estimatedItemSize - Place providers in root , not in individual screens
_layout.tsx - Use for manual padding,
useSafeAreaInsets()for simple wrappingSafeAreaView - Test on real device for haptics and performance verification
- 用包裹根布局,并设置
GestureHandlerRootViewstyle={{ flex: 1 }} - 所有图片都使用expo-image(缓存、blurhash、性能更优)
- 仅为主要操作(按钮、重要选择)添加触觉反馈——不要每个触摸都加
- 为所有FlashList组件设置
estimatedItemSize - 将提供者放在根目录的中,而非单个页面
_layout.tsx - 手动设置内边距时使用,简单包裹时使用SafeAreaView
useSafeAreaInsets() - 在真实设备上测试触觉反馈和性能
Anti-Patterns
反模式
- Using React Native instead of
Imageexpo-image - Using for large datasets instead of
FlatListFlashList - Forgetting (causes bottom sheet and gesture crashes)
GestureHandlerRootView - Overusing haptics on every interaction
- Hardcoding status bar height instead of using safe area insets
- Missing on FlashList (required prop, console warning)
estimatedItemSize - Placing inside ScrollView (causes layout issues)
SafeAreaView - Not including plugin in
expo-routerplugins arrayapp.json
- 使用React Native的而非
Imageexpo-image - 处理大型数据集时使用而非
FlatListFlashList - 忘记添加(会导致底部弹窗和手势崩溃)
GestureHandlerRootView - 过度使用触觉反馈,每个交互都触发
- 硬编码状态栏高度,而非使用安全区域内边距
- FlashList未设置(必填属性,控制台会发出警告)
estimatedItemSize - 在ScrollView内部放置(会导致布局问题)
SafeAreaView - 的plugins数组中未包含
app.json插件expo-router