React Native / Expo Patterns
Practical patterns for building production React Native apps with Expo. Covers navigation, state, data fetching, lists, styling, and native APIs. Pairs with the rules/react-native/ ruleset: rules say what to enforce, this skill shows how.
Libraries named below (NativeWind, Zustand/Jotai, TanStack Query) are common, well-established options shown for illustration — the patterns matter more than the specific package, and any equivalent works. Zod is used for validation to stay consistent with ECC's existing typescript/ rules.
These patterns assume the managed Expo workflow (Expo Router, EAS, expo-* modules) on the New Architecture (the default in recent Expo SDKs, mandatory from SDK 55+). They do NOT assume the browser DOM — React Native has no <div>, no URL bar, and no web data-fetching defaults.
When to Activate
Use this skill when:
- Building or editing React Native / Expo screens, components, or navigation
- Setting up routing with Expo Router (file-based
app/directory) - Deciding where state belongs (server cache vs client store vs route params vs form)
- Wiring data fetching with TanStack Query and validating responses with Zod
- Rendering long or heavy lists
- Choosing or applying a styling approach (NativeWind or StyleSheet)
- Accessing native device APIs (camera, location, notifications) or secure storage
- Reviewing RN code for mobile-specific issues
Do NOT use the web/React-DOM patterns here — URL-as-state, <div>, and SWR-for-browser do not apply to React Native.
Core Concepts
Project structure (Expo Router)
File-based routing under app/. Keep route files thin: they read and validate params, then delegate to a screen component that lives in components/ or features/.
Navigation: validate route params
Deep links and dynamic routes deliver untrusted strings. Validate them with Zod before use.
State: keep concerns separate
Do not duplicate server data into a client store. Each concern has its own home.
Prefer local useState until state genuinely needs sharing.
Data fetching: a cache library + Zod
Use a server-cache library (TanStack Query, SWR) instead of fetch-in-useEffect. Validate at the boundary and infer types from the schema. Handle loading, error, and empty states explicitly. (Example uses TanStack Query.)
Lists: virtualize, never map a big array in a ScrollView
Use FlashList (Shopify) for large or heterogeneous lists.
Styling: pick one system
StyleSheet.create() is the framework-native option; utility-class libraries (e.g. NativeWind) are a common alternative. Choose one and stay consistent. Never build style objects inline in JSX on hot paths.
Native APIs: wrap in hooks, clean up effects
Keep Expo SDK calls and subscriptions inside use* hooks, not in JSX. Always clean up.
Secure storage for tokens
Code Examples
A full screen: route → query → list → states
A form: React Hook Form + Zod resolver
Anti-Patterns
Best Practices
- Keep route files thin; put logic in screen components and
use*hooks. - Validate every external input (API responses, route params, push payloads) with Zod.
- Let TanStack Query own server state; keep client stores small.
- Always render loading, error, and empty states — never just a spinner with no fallback.
- Virtualize lists; memoize
renderItem; provide a stablekeyExtractor. - Use
react-native-reanimatedfor animation (UI thread); avoid heavy work on the JS thread. - Store tokens in
expo-secure-store; never trust the client for authorization. - Respect safe areas, Dynamic Type, and accessibility roles/labels from the start.
- Confirm New Architecture compatibility for every native dependency before release.
Related Skills
frontend-patterns— React/Next.js (web) patterns; useful for shared React concepts, but DOM-specific.coding-standards— TypeScript/JavaScript idioms that apply to RN code.tdd-workflow,e2e-testing— testing process (use Jest + React Native Testing Library, Maestro/Detox for RN).security-review— general security checklist that complements the RN bundle/secret guidance above.


