💻 Développement

dev-react-native-guide

Guide de développement React Native avec Expo et navigation.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-react-native-guide --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-react-native-guide -Launch"

🚀 Déjà installé ?

claude "/dev-react-native-guide"

Ou tapez /dev-react-native-guide dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

React NativeExpoRNreact-navigationnative modulesbridgemobile JavaScriptHermes

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-react-native-guide ~/.claude/skills/

Payload du plugin : skills/dev-react-native-guide · source éditable : dev-skills/react-native-guide

📖 Manuel

React Native Guide

1. Choix du workflow — critères de décision

CritèreExpo ManagedExpo BareRN CLI pur
Démarrage rapide
Accès natif complet
EAS Build/Update
SDK Expo prêt à l'emploiPartiel
Maintenance long termeFacileMoyenneÉlevée

Règle : commencer Expo Managed, migrer en Bare uniquement si un module natif custom est indispensable.

# Expo SDK 52 (LTS 2026), TypeScript, file-based routing
npx create-expo-app@latest MyApp --template blank-typescript
cd MyApp && npx expo install expo-router react-native-safe-area-context react-native-screens

2. Navigation — Expo Router (recommandé 2026)

Expo Router v3+ : routing basé sur les fichiers, deep linking automatique, typages TypeScript natifs.

app/
  _layout.tsx        ← root layout (Stack ou Tabs)
  index.tsx          ← écran "/"
  (tabs)/
    _layout.tsx      ← Tabs layout
    home.tsx         ← "/home"
    profile.tsx      ← "/profile"
  [id].tsx           ← route dynamique "/123"
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
  return <Stack screenOptions={{ headerShown: false }} />;
}

// Navigation typée
import { router } from 'expo-router';
router.push('/profile');
router.push({ pathname: '/[id]', params: { id: '42' } });

Si React Navigation v6 standalone : préférer createNativeStackNavigator (performances natives) sur createStackNavigator (JS pur).

3. State management — arbre de décision

Données locales à un composant  →  useState / useReducer
Partage entre quelques écrans   →  Context + useReducer
Cache serveur / API             →  TanStack Query v5
État global UI                  →  Zustand
Projet legacy complexe          →  Redux Toolkit
// Zustand — store minimal typé
import { create } from 'zustand';
interface AuthStore { token: string | null; setToken: (t: string) => void; }
export const useAuthStore = create<AuthStore>((set) => ({
  token: null,
  setToken: (token) => set({ token }),
}));

// TanStack Query — fetch avec cache
const { data, isLoading, error } = useQuery({
  queryKey: ['user', id],
  queryFn: () => api.getUser(id),
  staleTime: 60_000,
});

4. UI et styling

// Reanimated — animation sur le thread UI
import Animated, { useSharedValue, withSpring, useAnimatedStyle } from 'react-native-reanimated';

const offset = useSharedValue(0);
const style = useAnimatedStyle(() => ({ transform: [{ translateX: offset.value }] }));
// Déclencher : offset.value = withSpring(100);
<Animated.View style={[styles.box, style]} />

5. Listes performantes

FlatList cause des janks sur les longues listes. Migrer vers FlashList :

npx expo install @shopify/flash-list
import { FlashList } from '@shopify/flash-list';
<FlashList
  data={items}
  renderItem={({ item }) => <ItemCard item={item} />}
  estimatedItemSize={80}   // ← obligatoire, détermine les perfs
  keyExtractor={(item) => item.id}
/>

6. Stockage local

BesoinSolution
Simple clé-valeur async@react-native-async-storage/async-storage
Haute perf synchronereact-native-mmkv
SQLite relationnelexpo-sqlite (Expo) ou op-sqlite (Bare/RN CLI)
Sécurisé (tokens)expo-secure-store
// MMKV — synchrone, 10x plus rapide qu'AsyncStorage
import { MMKV } from 'react-native-mmkv';
const storage = new MMKV();
storage.set('token', 'abc123');
const token = storage.getString('token'); // synchrone

7. Modules natifs et nouvelle architecture

React Native 0.74+ : nouvelle architecture activée par défaut (JSI, Fabric, TurboModules).

# Vérifier la compatibilité d'un package
npx react-native-new-architecture-check

Ordre de priorité pour les modules natifs :

  1. Expo SDK (caméra, notifications, biométrie, localisation) — zéro config
  2. Community packages compatibles nouvelle architecture
  3. Expo Modules API (Swift/Kotlin) pour un module custom
// Expo Module API (Kotlin) — module natif minimal
class MyModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("MyModule")
    Function("greet") { name: String -> "Hello, $name!" }
  }
}

8. Build et déploiement — EAS

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

# Build cloud (sans Mac pour iOS)
eas build --platform ios --profile production
eas build --platform android --profile production

# OTA update (sans passer par le store)
eas update --branch production --message "fix: crash liste"

# Soumettre au store
eas submit --platform ios
eas submit --platform android

eas.json — profils types :

{
  "build": {
    "development": { "developmentClient": true, "distribution": "internal" },
    "preview": { "distribution": "internal" },
    "production": { "autoIncrement": true }
  }
}

9. Performance — checklist

10. Garde-fous et anti-patterns

Ne pas faire :

// ❌ setState dans une boucle → re-rendus en cascade
items.forEach(item => setCount(count + 1));
// ✅ un seul setState avec la valeur finale
setCount(items.length);

// ❌ inline function dans renderItem → rerend à chaque frame
<FlatList renderItem={({ item }) => <Card item={item} />} />
// ✅ extraire le composant ou mémoïser
const renderItem = useCallback(({ item }) => <Card item={item} />, []);

// ❌ StyleSheet inline → nouvel objet à chaque rendu
<View style={{ flex: 1, padding: 16 }} />
// ✅ StyleSheet.create (compilé une fois)
const styles = StyleSheet.create({ container: { flex: 1, padding: 16 } });

// ❌ useEffect sans cleanup sur les listeners
useEffect(() => { subscription = subscribe(); }, []);
// ✅
useEffect(() => { const sub = subscribe(); return () => sub.remove(); }, []);

Pièges courants :

Références rapides