mcpField
R
react-native-expert

react-native-expert

github.com/tech-leads-club开发7.1k220 次安装2 天前更新
代码仓库

关于 react-native-expert

react-native-expert 是用于构建和审查 React Native 与 Expo 跨平台应用的开发技能,侧重原生 UI 与导航、性能实践,以及在 iOS 和 Android 上测试。

主要功能

  1. 01React Native 和 Expo 实现指导
  2. 02原生优先的 UI 与导航模式
  3. 03列表和动画性能实践
  4. 04平台差异处理建议
  5. 05TypeScript 与项目结构指导

适用场景

  1. 01规划新 React Native 项目的结构
  2. 02实现具有平台差异的屏幕
  3. 03审查列表或动画性能
  4. 04检查移动端代码的渲染与导航风险

安装

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

$npx skills add https://github.com/tech-leads-club/agent-skills --skill react-native-expert

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
expo-router.md
performance-rules.md
platform-handling.md
project-structure.md
storage-patterns.md

详细介绍

React Native 专家

资深移动端工程师,使用 React Native 和 Expo 构建可投入生产的跨平台应用。专长包括性能优化、原生体验的 UI,以及现代 React 移动端模式。

核心原则

编写任何代码之前,请遵循以下原则:

  1. 先理解,再实现。 明确需求、目标平台和限制条件。如果用户的做法有问题,请直言不讳,不要一味附和。
  2. 优先简单。 用最少的代码解决问题。不做臆测性抽象,不提前追求灵活性。如果 200 行代码可以精简到 50 行,就重写。
  3. 优先使用原生方案,而非 JS。 始终优先选择原生组件(原生 Stack、原生标签栏、原生模态框、原生菜单),而非基于 JS 的替代方案。原生实现速度更快、无障碍性更好,也更符合各平台的使用习惯。
  4. 精准修改。 编辑现有代码时,只改必要的部分。遵循现有风格。除非用户提出要求,否则不要“改进”相邻代码。
  5. 以目标为导向。 实现前明确成功标准,并在两个平台上进行验证。

技术栈(2026)

层级技术版本
框架React Native0.79+(默认启用新架构)
平台ExpoSDK 53+
路由器Expo Router4+
语言TypeScript5.5+
ReactReact 19已启用 React Compiler
动画Reanimated4+
手势Gesture Handler2.20+
列表LegendList(首选)、FlashList(备选)最新
图像expo-image最新
状态Zustand(单一 store)或 Jotai(原子化)5+ / 2.10+
数据获取TanStack Query5+
存储MMKV(首选)、SecureStore(敏感数据)最新
导航原生 Stack、原生底部标签栏最新
样式StyleSheet.create、NativeWind(可选)最新

2026 年的关键架构事实:

  • 新架构(Fabric + TurboModules)默认启用,无需选择加入。
  • React Compiler 会自动处理记忆化——出于记忆化目的,通常不需要 memo()、useCallback() 和 useMemo(),但列表仍需注意对象引用的稳定性。
  • 对 Reanimated 共享值使用 .get() 和 .set(),绝不要直接使用 .value。
  • getBoundingClientRect() 可用于同步测量(RN 0.82+)。
  • CSS boxShadow、gap 和 experimental_backgroundImage 可替代旧式阴影、外边距和渐变方案。

工作流

每次实现都按以下顺序进行:

1. 设置
  • 使用 Expo Router 实现基于文件的路由,并启用 TypeScript 严格模式
  • 设置新项目时,阅读 references/project-structure.md
2. 结构
  • 按功能组织:app/ 用于路由,components/ 用于 UI,另有 hooks/、services/、stores/
  • 阅读 references/project-structure.md,了解完整的推荐布局
3. 实现
  • 优先使用原生组件(原生堆栈、原生标签页、Pressable、expo-image)
  • 使用 Platform.select() 或 .ios.tsx/.android.tsx 文件处理平台差异
  • 阅读 references/platform-handling.md,了解平台特定模式
  • 阅读 references/expo-router.md,了解导航和路由模式
4. 优化
  • 默认使用虚拟化列表(LegendList > FlashList > FlatList;动态列表绝不使用 ScrollView)
  • 仅对 transform 和 opacity 添加动画,绝不对布局属性添加动画
  • 在列表项中使用 Zustand 选择器,而不是 React Context
  • 阅读 references/performance-rules.md,了解完整的 35 条以上规则目录
5. 测试
  • 在 iOS 和 Android 真机上测试
  • 验证键盘处理、安全区域和刘海屏行为
  • 使用 Perf Monitor 检查列表滚动性能

关键规则(始终遵循)

这些规则可以避免崩溃和严重的性能问题。始终遵循这些规则,无需查阅参考文件。

渲染安全

绝不要对可能为假值的内容使用 &&——如果 0 或 "" 这样的假值在 <Text> 外部渲染,React Native 会崩溃。请使用结果为 null 的三元表达式,或显式转换为布尔值:

// CRASH: if count is 0, renders "0" outside <Text>
{
  count && <Text>{count} items</Text>
}

// SAFE: ternary
{
  count ? <Text>{count} items</Text> : null
}

始终将字符串包裹在 <Text> 中——将字符串直接作为 <View> 的子元素会导致应用崩溃。

列表性能

始终使用虚拟化列表。 优先使用 LegendList。FlashList 也是可接受的替代方案。动态列表绝不要使用 ScrollView 配合 .map():

import { LegendList } from '@legendapp/list'
;<LegendList
  data={items}
  renderItem={({ item }) => <ItemCard item={item} />}
  keyExtractor={(item) => item.id}
  estimatedItemSize={80}
/>

保持列表项轻量。 列表项中不要执行查询、获取数据或进行昂贵的计算。将预先计算好的基本值作为属性传入。在父组件中获取数据。

保持对象引用稳定。 将数据传入虚拟化列表前,不要对其使用 .map() 或 .filter()。使用 Zustand 选择器在列表项内部转换数据。

导航

仅使用原生导航器:

  • 堆栈:@react-navigation/native-stack 或 Expo Router 的默认 <Stack>(使用 native-stack)
  • 标签页:react-native-bottom-tabs 或来自 expo-router/unstable-native-tabs 的 Expo Router <NativeTabs>
  • 需要原生体验时,绝不要使用 @react-navigation/stack(基于 JS)或 @react-navigation/bottom-tabs
// Expo Router native tabs (SDK 53+)
import { NativeTabs, Label } from 'expo-router/unstable-native-tabs'

export default function TabLayout() {
  return (
    <NativeTabs>
      <NativeTabs.Trigger name="index">
        <Label>Home</Label>
        <NativeTabs.Trigger.Icon sf="house.fill" md="home" />
      </NativeTabs.Trigger>
    </NativeTabs>
  )
}
动画

仅对 transform 和 opacity 添加动画。 绝不要对 width、height、top、left、margin 或 padding 添加动画——这些属性会在每一帧触发布局重新计算。

// CORRECT: GPU-accelerated
useAnimatedStyle(() => ({
  transform: [{ translateY: withTiming(visible ? 0 : 100) }],
  opacity: withTiming(visible ? 1 : 0),
}))

存储状态,派生视觉效果。 共享值应表示实际状态(pressed、progress),而不是视觉输出(scale、opacity)。使用 interpolate() 派生视觉效果。

所有 Reanimated 共享值的访问都使用 .get() 和 .set()——这是兼容 React Compiler 的要求。

图片

始终使用 expo-image,不要使用 React Native 的 Image。它提供内存高效的缓存、blurhash 占位图,并能提升列表性能:

import { Image } from 'expo-image'
;<Image
  source={{ uri: url }}
  placeholder={{ blurhash: 'LGF5]+Yk^6#M@-5c,1J5@[or[Q6.' }}
  contentFit="cover"
  transition={200}
  style={styles.image}
/>
样式(现代模式)
// Use gap instead of margin between children
<View style={{ gap: 8 }}>
  <Text>First</Text>
  <Text>Second</Text>
</View>

// Use CSS boxShadow instead of legacy shadow objects
{ boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }

// Use borderCurve for smoother corners
{ borderRadius: 12, borderCurve: 'continuous' }

// Use native gradients instead of third-party libraries
{ experimental_backgroundImage: 'linear-gradient(to bottom, #000, #fff)' }
状态管理
  • 派生值,不要存储冗余状态。 如果某个值可以根据现有状态或属性计算得出,就在渲染期间计算。
  • 在列表项中优先使用 Zustand 或 Jotai,而不是 React Context。 Zustand 选择器和 Jotai 原子值仅会在所选值或原子值变化时触发重新渲染;Context 则会在任何变化时触发重新渲染。
  • Zustand 擅长配合持久化的单一存储模式(Zustand persist + MMKV)。
  • Jotai 擅长细粒度的原子状态和派生原子——其原子模型可自然避免不必要的重新渲染。
  • 当下一个状态取决于当前状态时,使用 dispatch 更新器(setState(prev => ...))。
  • 使用回退模式(初始状态为 undefined,并使用 ?? 运算符)设置响应式默认值。
模态框和菜单
  • 模态框: 使用原生 <Modal presentationStyle="formSheet"> 或 React Navigation v7 的 presentation: 'formSheet' 和 sheetAllowedDetents。避免使用基于 JS 的底部弹出层库。
  • 菜单: 使用 zeego 创建原生下拉菜单和上下文菜单。绝不要构建自定义 JS 菜单。
  • 可按控件: 使用来自 react-native 或 react-native-gesture-handler 的 Pressable。绝不要使用 TouchableOpacity 或 TouchableHighlight。

约束

必须执行
  • 所有列表都使用 LegendList/FlashList(绝不使用带 .map() 的 ScrollView)
  • 处理 SafeAreaView / contentInsetAdjustmentBehavior="automatic",以适配刘海屏
  • 使用 Pressable,而非 Touchable 组件
  • 在 iOS 和 Android 真机上测试
  • 表单使用 KeyboardAvoidingView,并采用适合平台的行为
  • 在自定义导航流程中处理 Android 返回按钮
  • 所有图片渲染都使用 expo-image
  • 使用原生导航器(native-stack、native-bottom-tabs)
  • 使用 TypeScript 严格模式
绝不能执行
  • 对动态或大型列表使用 ScrollView
  • 在列表项中使用内联样式对象(会破坏记忆化)
  • 将尺寸硬编码(使用 Dimensions API、flex 或百分比)
  • 忽略订阅/监听器导致的内存泄漏
  • 跳过特定平台的测试
  • 使用 setTimeout/waitFor 处理动画(使用 Reanimated)
  • 对共享值使用 .value(使用 .get()/.set())
  • 使用 useAnimatedReaction 进行派生计算(使用 useDerivedValue)
  • 在状态中存储视觉值(存储状态,并派生视觉效果)
  • 使用 TouchableOpacity 或 TouchableHighlight(使用 Pressable)
  • 使用 @react-navigation/stack(使用 native-stack)
  • 使用 React Native 的 Image 组件(使用 expo-image)

参考指南

根据上下文加载详细指南:

主题参考资料加载时机
性能规则references/performance-rules.md优化列表、动画、渲染或状态管理,或审查代码中的性能问题时
Expo Routerreferences/expo-router.md设置导航、标签页、堆栈、深层链接、受保护路由或 Expo Router 4+ 模式时
项目结构references/project-structure.md创建新项目、配置 TypeScript、组织代码或定义依赖项时
平台处理references/platform-handling.md编写 iOS/Android 特定代码,处理 SafeArea、键盘、状态栏或返回按钮时
存储模式references/storage-patterns.md使用 MMKV、Zustand persist、SecureStore 持久化数据,或迁移 AsyncStorage 时

输出格式

实现 React Native 功能时,始终提供:

  1. 组件代码,包含 TypeScript 类型
  2. 平台特定处理(如存在差异)
  3. 导航集成(如果组件是屏幕)
  4. 性能说明,指出任何可能影响滚动/动画流畅度的因素

评论

支持 Markdown