AgentSkillsCN

expo-react-native

Expo/React Native 项目约定和模式。 适用场景:使用 Expo 构建跨平台移动应用、React Native 屏幕、移动端专用逻辑。 不适用于:UX 决策(使用 ux-design)、令牌/组件设计(使用 design-system)、仅限 Web 的功能。 工作流程:本技能(构建移动应用)→ velcel-react-native-skills(如有需要进行重构和性能优化)。

SKILL.md
--- frontmatter
name: expo-react-native
description: |
  Expo/React Native project conventions and patterns.
  Use when: building cross-platform mobile apps with Expo, React Native screens, mobile-specific logic.
  Do not use for: UX decisions (use ux-design), token/component design (use design-system), web-only features.
  Workflow: this skill (building mobile apps) -> velcel-react-native-skills (refactoring and performance optimization if needed).
references:
  - examples.md    # Auth Guard, State Persistence, Forms, Animations code

Expo & React Native Patterns

For latest APIs, use context7.

Package manager: Use bun for all commands.


Project Structure (Feature-Sliced Design)

For Feature-Sliced Design structure use Context7

code
app/                 # Expo Router (file-based routing)
├── _layout.tsx      # Root layout
├── index.tsx        # Home (/)
└── some-page/
    └── index.tsx    # /some-page (routing + page composition)
src/
├── app/             # App-wide settings, providers, global styles
│   └── providers/
├── widgets/         # Large composite blocks (Header, Sidebar, Feed)
├── features/        # User interactions (auth, send-comment, add-to-cart)
│   └── auth/
│       ├── ui/
│       ├── model/
│       └── api/
├── entities/        # Business entities (user, product, order)
│   └── user/
│       ├── ui/
│       ├── model/
│       └── api/
└── shared/          # Reusable infrastructure
    ├── ui/          # Design system
    ├── lib/         # Utilities, helpers
    ├── api/         # API client
    └── config/      # Environment, constants

FSD Layer Rules

LayerCan import fromCannot import from
appAll layers below-
widgetsfeatures, entities, sharedapp
featuresentities, sharedapp, widgets
entitiessharedapp, widgets, features
shared-All layers above

Rule: Layers can only import from layers below. Never above.


Preferred Stack

CategoryChoiceWhy
State (server)TanStack QueryCaching, background sync
State (client)ZustandSimple, no boilerplate
StorageMMKV10x faster than AsyncStorage
FormsTanStack Form + ZodType-safe, good validation
ListsFlashListRecycling, better perf than FlatList
AnimationReanimated + Gesture Handler60fps, runs on UI thread

Headless Patterns

Rule: Separate WHAT (logic) from HOW (presentation).

tsx
// ❌ Before: 800-line single file with 15 useStates
const DiaryHistory = () => {
  const [meals, setMeals] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  // ... 500+ lines
};
tsx
// ✅ After: Main component is composition only
const DiaryHistory = () => {
  const { range, setRange } = useDateRange();
  const { meals, isLoading, loadMore } = useMealHistory({ range });
  const { sections } = useSortedMeals(meals);

  return (
    <Screen>
      <FilterBar range={range} onRangeChange={setRange} />
      <MealSectionList sections={sections} onEndReached={loadMore} />
    </Screen>
  );
};

Rule: Main component does composition only. Logic goes in hooks.

Hook Interface Guidelines

tsx
// ✅ Clean, predictable return
const { data, isLoading, error, refetch } = useQuery();
const { selected, toggle, clear } = useSelection();

Performance Rules

RuleWhy
FlashList over FlatListRecycling, handles 10k+ items
Memoize components with callbacksPrevent unnecessary re-renders
useCallback for handlers passed downStable references
InteractionManager.runAfterInteractionsDefer heavy work until after navigation
Test on physical deviceSimulators hide real performance issues

Rule: If it scrolls, use FlashList. If it's slow, profile on real device.


Quick Checklist

Architecture

  • Main component is composition only (no 15 useStates)
  • Logic extracted to custom hooks
  • Hook interfaces are clean and predictable

Performance

  • Using FlashList for lists (not FlatList)
  • Components memoized where needed
  • Heavy work deferred with InteractionManager
  • Tested on physical device (not just simulator)

State & Data

  • Server state in TanStack Query
  • Client state in Zustand
  • Persistent state uses MMKV (not AsyncStorage)

Platform

  • Works on both iOS and Android
  • Safe areas handled
  • Keyboard doesn't cover inputs

Design System

  • Using tokens from design-system (no hardcoded values)
  • Touch targets 44pt+

Security Configuration

ItemValue
Token storageSecureStore (not AsyncStorage)
JWT access token1 hour
JWT refresh token1 year
Certificate pinningRequired for sensitive APIs