react-native-architecture

React Native Architecture

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-native-architecture" with this command: npx skills add sivag-lab/roth_mcp/sivag-lab-roth-mcp-react-native-architecture

React Native Architecture

Production patterns for React Native with Expo, covering project setup, navigation, state management, native integration, offline-first, performance, and CI/CD.

When to Use

  • Starting a new React Native or Expo project

  • Implementing complex navigation patterns

  • Integrating native modules and platform APIs

  • Building offline-first mobile applications

  • Optimizing React Native performance

  • Setting up CI/CD for mobile releases

Project Setup (Expo)

Create new Expo project

npx create-expo-app@latest my-app --template tabs cd my-app

Or with blank TypeScript template

npx create-expo-app@latest my-app -t expo-template-blank-typescript

Recommended Project Structure

src/ app/ # Expo Router file-based routes (tabs)/ # Tab navigator group index.tsx # Home tab profile.tsx # Profile tab _layout.tsx # Root layout +not-found.tsx # 404 screen components/ # Shared UI components ui/ # Primitives (Button, Input, Card) hooks/ # Custom hooks lib/ # Utilities, API client, storage store/ # State management (Zustand) constants/ # Theme, config, enums types/ # TypeScript definitions

Navigation

Expo Router (Recommended)

File-based routing, similar to Next.js.

// app/_layout.tsx — Root layout import { Stack } from 'expo-router';

export default function RootLayout() { return ( <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> <Stack.Screen name="modal" options={{ presentation: 'modal' }} /> </Stack> ); }

// app/(tabs)/_layout.tsx — Tab navigator import { Tabs } from 'expo-router'; import { Ionicons } from '@expo/vector-icons';

export default function TabLayout() { return ( <Tabs> <Tabs.Screen name="index" options={{ title: 'Home', tabBarIcon: ({ color }) => <Ionicons name="home" size={24} color={color} />, }} /> <Tabs.Screen name="profile" options={{ title: 'Profile' }} /> </Tabs> ); }

Navigation Patterns

Pattern Implementation

Stack <Stack> in layout — push/pop screens

Tabs <Tabs> in layout — bottom tab bar

Drawer expo-router with drawer layout

Modal presentation: 'modal' in screen options

Deep linking Automatic with Expo Router file paths

Auth flow Conditional layout based on auth state

Auth-Protected Routes

// app/_layout.tsx import { Redirect } from 'expo-router'; import { useAuth } from '@/hooks/useAuth';

export default function RootLayout() { const { isAuthenticated, isLoading } = useAuth();

if (isLoading) return <SplashScreen />; if (!isAuthenticated) return <Redirect href="/login" />;

return <Stack />; }

State Management

Scope Solution

Component useState , useReducer

Server data TanStack Query (React Query)

Global UI Zustand

Persistent MMKV + Zustand persist

Forms React Hook Form

Zustand Store

import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import { zustandStorage } from '@/lib/mmkv-storage';

interface AppStore { theme: 'light' | 'dark'; setTheme: (theme: 'light' | 'dark') => void; }

export const useAppStore = create<AppStore>()( persist( (set) => ({ theme: 'light', setTheme: (theme) => set({ theme }), }), { name: 'app-store', storage: createJSONStorage(() => zustandStorage) } ) );

TanStack Query for API Data

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

function useUser(id: string) { return useQuery({ queryKey: ['user', id], queryFn: () => api.getUser(id), staleTime: 5 * 60 * 1000, }); }

function useUpdateUser() { const qc = useQueryClient(); return useMutation({ mutationFn: api.updateUser, onSuccess: (_, vars) => qc.invalidateQueries({ queryKey: ['user', vars.id] }), }); }

Native Modules & Platform APIs

Using Expo Modules

npx expo install expo-camera expo-location expo-notifications expo-file-system

import * as Location from 'expo-location';

async function getLocation() { const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') throw new Error('Permission denied'); return Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High }); }

Platform-Specific Code

import { Platform } from 'react-native';

const styles = { shadow: Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1 }, android: { elevation: 4 }, }), };

// File-based: MyComponent.ios.tsx / MyComponent.android.tsx

Offline-First Architecture

Storage Options

Solution Use For Speed

MMKV Key-value, small data, preferences Fastest

SQLite (expo-sqlite) Structured data, queries, relations Fast

AsyncStorage Legacy key-value (avoid for new) Slow

FileSystem Large files, downloads, cache Varies

Offline Queue Pattern

import NetInfo from '@react-native-community/netinfo';

class OfflineQueue { private queue: PendingAction[] = [];

async enqueue(action: PendingAction) { this.queue.push(action); await this.persist(); this.processIfOnline(); }

private async processIfOnline() { const { isConnected } = await NetInfo.fetch(); if (!isConnected) return;

while (this.queue.length > 0) {
  const action = this.queue[0];
  try {
    await this.execute(action);
    this.queue.shift();
    await this.persist();
  } catch {
    break; // Retry later
  }
}

} }

Performance

Optimization Checklist

Area Action

Lists Use FlashList instead of FlatList

Images Use expo-image (caching, blurhash, transitions)

Animations Use react-native-reanimated (UI thread)

Heavy computation Move to worklet or background thread

Re-renders Profile with React DevTools, apply memo

Bundle Use Hermes engine (default in Expo 49+)

Startup Minimize root component, lazy load screens

FlashList (Drop-in FlatList Replacement)

import { FlashList } from '@shopify/flash-list';

<FlashList data={items} renderItem={({ item }) => <ItemCard item={item} />} estimatedItemSize={80} keyExtractor={(item) => item.id} />

Image Optimization

import { Image } from 'expo-image';

<Image source={{ uri: imageUrl }} placeholder={{ blurhash: 'LKO2?U%2Tw=w]~RBVZRi};RPxuwH' }} contentFit="cover" transition={200} style={{ width: 200, height: 200 }} />

CI/CD with EAS Build

Setup

npm install -g eas-cli eas login eas build:configure

eas.json

{ "build": { "development": { "developmentClient": true, "distribution": "internal" }, "preview": { "distribution": "internal", "ios": { "simulator": true } }, "production": {} }, "submit": { "production": { "ios": { "appleId": "you@example.com", "ascAppId": "123456789" }, "android": { "serviceAccountKeyPath": "./google-services.json" } } } }

Build Commands

eas build --platform ios --profile preview # iOS simulator build eas build --platform android --profile preview # Android APK eas build --platform all --profile production # Production builds eas submit --platform all # Submit to stores eas update --branch preview --message "Bug fix" # OTA update

Project Checklist

  • Expo SDK latest (or target version)

  • TypeScript configured with strict mode

  • Expo Router for navigation

  • Zustand + MMKV for state persistence

  • TanStack Query for server state

  • FlashList for performant lists

  • expo-image for optimized images

  • Reanimated for animations

  • EAS Build configured for CI/CD

  • Deep linking tested

  • Offline handling implemented

  • Platform-specific code isolated

  • Error boundaries at route level

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

react-modernization

No summary provided by upstream source.

Repository SourceNeeds Review
General

notebooklm

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-flow-node-ts

No summary provided by upstream source.

Repository SourceNeeds Review
General

design-md

No summary provided by upstream source.

Repository SourceNeeds Review