mcpField
R
react-native

react-native

github.com/jezweb开发1.1k1.3k 次安装3 周前更新
代码仓库

关于 react-native

面向 React Native 和 Expo 开发者的移动应用模式指南,按影响程度整理性能与架构建议,涵盖列表、动画、导航和 Expo 工作流。

主要功能

  1. 01按影响程度排列规则
  2. 02列表与滚动性能建议
  3. 03动画与手势模式
  4. 04导航和界面建议
  5. 05状态、数据与媒体建议
  6. 06Expo 工作流及测试指南

适用场景

  1. 01创建新的 React Native 或 Expo 应用
  2. 02排查列表滚动卡顿
  3. 03评审移动端性能问题
  4. 04设置 Expo 项目与测试流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jezweb/claude-skills --skill react-native

安装后在 Claude Code 中输入/react-native确认已加载。

详细介绍

React Native 模式

适用于 React Native + Expo 应用的性能和架构模式。规则按影响程度排序——先修复 CRITICAL,再处理 MEDIUM。

这是一个起点。随着你构建更多移动应用,这项技能也会不断扩展。

适用场景

  • 构建新的 React Native 或 Expo 应用
  • 优化列表和滚动性能
  • 实现动画
  • 检查移动端代码中的性能问题
  • 设置新的 Expo 项目

1. 列表性能(CRITICAL)

列表是 React Native 中最常见的性能问题。滚动卡顿会严重影响整个应用的体验。

模式问题修复方法
使用 ScrollView 显示数据<ScrollView> 会一次性渲染所有项使用 <FlatList> 或 <FlashList>——采用虚拟化,只渲染可见项
缺少 keyExtractorFlatList 未设置 keyExtractor → 导致不必要的重新渲染keyExtractor={(item) => item.id}——为每项提供稳定且唯一的键
renderItem 过于复杂renderItem 中的开销较大的组件会在每次滚动时重新渲染使用 React.memo 包装,或提取为独立组件
renderItem 中使用内联函数renderItem={({ item }) => <Row onPress={() => nav(item.id)} />}提取处理函数:const handlePress = useCallback(...)
未设置 getItemLayoutFlatList 滚动时会测量每一项(开销较大)为固定高度的项提供 getItemLayout:(data, index) => ({ length: 80, offset: 80 * index, index })
FlashListFlatList 表现不错,但 FlashList 更适合大型列表@shopify/flash-list——可直接替换,采用视图回收架构
列表中使用大图片全分辨率图片在主线程解码使用 expo-image,设置占位图和过渡效果,并指定尺寸
FlatList 检查清单

每个 FlatList 都应包含:

<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={renderItem}           // Memoised component
  getItemLayout={getItemLayout}     // If items are fixed height
  initialNumToRender={10}           // Don't render 100 items on mount
  maxToRenderPerBatch={10}          // Batch size for off-screen rendering
  windowSize={5}                    // How many screens to keep in memory
  removeClippedSubviews={true}      // Unmount off-screen items (Android)
/>

2. 动画(HIGH)

原生动画在 UI 线程上运行。JS 动画会阻塞 JS 线程并导致卡顿。

模式问题修复方法
使用 Animated API 实现复杂动画Animated 在 JS 线程上运行,会阻塞交互使用 react-native-reanimated——在 UI 线程上运行
布局动画项目出现或消失时没有过渡效果LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
共享元素过渡在屏幕间导航时,元素会瞬间跳转使用 react-native-reanimated 的共享过渡,或 expo-router 的共享元素
手势与动画拖动或滑动感觉迟缓使用 react-native-gesture-handler + reanimated worklets——全部在 UI 线程上运行
测量布局onLayout 触发太晚,导致闪烁使用带共享值的 useAnimatedStyle,实现即时响应
Reanimated 基础
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';

function AnimatedBox() {
  const offset = useSharedValue(0);
  const style = useAnimatedStyle(() => ({
    transform: [{ translateX: withSpring(offset.value) }],
  }));

  return (
    <GestureDetector gesture={panGesture}>
      <Animated.View style={[styles.box, style]} />
    </GestureDetector>
  );
}

3. 导航(HIGH)

模式问题修复方法
Expo Router面向 React Native 的基于文件的路由(类似 Next.js)使用包含 _layout.tsx 文件的 app/ 目录。新 Expo 项目优先采用此方案。
堆栈中的重型屏幕每个屏幕都会在堆栈中保持挂载状态对无需保持状态的屏幕使用 unmountOnBlur: true
深度链接应用无法响应 URLExpo Router 会自动处理。对于裸 React Native 项目:配置 Linking API
标签页徽标更新聚焦标签页时,徽标计数不会更新使用 useIsFocused(),或在获得焦点时重新获取数据:useFocusEffect(useCallback(...))
导航状态持久化应用进入后台或被终止后会丢失位置使用 AsyncStorage 配合 onStateChange + initialState
Expo Router 结构
app/
├── _layout.tsx          # Root layout (tab navigator)
├── index.tsx            # Home tab
├── (tabs)/
│   ├── _layout.tsx      # Tab bar config
│   ├── home.tsx
│   ├── search.tsx
│   └── profile.tsx
├── [id].tsx             # Dynamic route
└── modal.tsx            # Modal route

4. UI 模式(高优先级)

模式问题修复方案
安全区域内容被刘海或主屏幕指示条遮挡使用 react-native-safe-area-context 中的 <SafeAreaView> 或 useSafeAreaInsets()
键盘避让表单字段被键盘遮挡<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
平台特定代码iOS 和 Android 需要不同的行为Platform.select({ ios: ..., android: ... }) 或 .ios.tsx / .android.tsx 文件
状态栏状态栏与内容重叠或颜色不正确在根布局中使用来自 expo-status-bar 的 <StatusBar style="auto" />
触控目标按钮太小,难以点击最小尺寸为 44x44pt。使用 hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
触觉反馈点击时没有反馈expo-haptics — 在重要操作时调用 Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)

5. 图像和媒体(中优先级)

模式问题修复方案
图像组件react-native 中的 <Image> 功能基础使用 expo-image — 支持缓存、占位图、过渡效果和 blurhash
未指定尺寸的远程图像图像加载时布局会发生偏移始终指定 width 和 height,或使用 aspectRatio
大型图像Android 上发生 OOM 崩溃在服务器端调整尺寸,或使用能处理内存问题的 expo-image
SVG原生不支持 SVG导入 SVG 时使用 react-native-svg + react-native-svg-transformer
视频视频播放使用 expo-av 或 expo-video(较新的 API)

6. 状态和数据(中优先级)

模式问题修复方案
使用 AsyncStorage 存储复杂数据每次读取都要进行 JSON 解析和序列化使用 MMKV(react-native-mmkv)——速度比 AsyncStorage 快 30 倍
全局状态简单状态也需要编写大量 Redux/MobX 样板代码使用 Zustand——轻量精简,与 React Native 配合出色
服务端状态手动处理 fetch、加载、错误和缓存使用 TanStack Query——与 Web 端相同,可在 React Native 中运行
离线优先没有网络时应用无法使用使用 TanStack Query persistQueryClient + MMKV;复杂离线场景则使用 WatermelonDB
深层状态更新更新嵌套对象时需要大量使用展开运算符通过 Zustand 使用 Immer:set(produce(state => { state.user.name = 'new' }))

7. Expo 工作流(中优先级)

模式适用场景用法
开发构建需要原生模块npx expo run:ios 或 eas build --profile development
Expo Go快速原型开发,无需原生模块npx expo start — 扫描二维码
EAS BuildCI/CD、应用商店构建eas build --platform ios --profile production
EAS Update无需应用商店审核即可快速修复eas update --branch production --message "Fix bug"
配置插件无需 eject 即可修改原生配置使用 expo-build-properties 或自定义配置插件配置 app.config.ts
环境变量为不同构建使用不同配置eas.json 构建配置文件 + expo-constants
新建项目
npx create-expo-app my-app --template tabs
cd my-app
npx expo install expo-image react-native-reanimated react-native-gesture-handler react-native-safe-area-context

8. 测试(低至中优先级)

工具用途配置
Jest单元测试、Hook 测试Expo 默认包含
React Native Testing Library组件测试@testing-library/react-native
Detox在真实设备或模拟器上进行 E2E 测试detox — Wix 的测试框架
Maestro使用 YAML 流程进行 E2E 测试maestro test flow.yaml — 比 Detox 更简单

常见问题

问题解决方法
Metro 打包器缓存npx expo start --clear
Pod 安装问题(iOS)cd ios && pod install --repo-update
Reanimated 无法正常工作必须作为首个导入项:在根目录中使用 import 'react-native-reanimated'
Expo SDK 升级更新 SDK 版本后运行 npx expo install --fix
Android 构建失败检查 gradle.properties 中的内存设置:org.gradle.jvmargs=-Xmx4g
iOS 模拟器运行缓慢使用实体设备进行性能测试——模拟器无法反映实际性能

评论

支持 Markdown