Communitygithub.com

react-native-muster

Muster für React Native- und Expo-Apps – Expo Router Navigation, Zustandstrennung (Server/Client/Route/Form), TanStack Query Datenabruf mit Zod, performante Listen, NativeWind/StyleSheet Styling, native APIs und sicherer Speicher. Verwenden beim Erstellen oder Bearbeiten von React Native / Expo Screens, Komponenten, Navigation oder Datenebenen.

Was ist react-native-muster?

Dieses Skill beschreibt praktische Muster für die Entwicklung produktionsreifer React Native Apps mit Expo. Es deckt Navigation, Zustandsverwaltung, Datenabruf, Listen, Styling und native APIs ab. Es wird aktiviert, wenn Sie React Native/Expo Screens, Komponenten, Navigation oder Datenebenen erstellen oder bearbeiten. Das Skill betont die Trennung von Zuständen: Serverdaten gehören in eine Cache-Bibliothek (z. B. TanStack Query), Client/UI-Zustand in einen leichten Store (Zustand, Jotai), Routenparameter in Expo Router und Formularzustand in eine Formularbibliothek. Es zeigt, wie man Routenparameter mit Zod validiert, Daten mit TanStack Query abruft und validiert, Listen mit FlatList oder FlashList virtualisiert und native APIs über benutzerdefinierte Hooks kapselt. Es behandelt auch sicheres Speichern mit expo-secure-store und gibt Anti-Patterns und Best Practices. Das Skill ist plattformunabhängig und funktioniert mit jedem äquivalenten Tool, verwendet aber die genannten Bibliotheken als Beispiele.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/react-native-patterns

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

React Native / Expo Muster

Praktische Muster für die Entwicklung produktionsreifer React Native Apps mit Expo. Behandelt Navigation, Zustand, Datenabruf, Listen, Styling und native APIs. Ergänzt das rules/react-native/ Regelwerk: Die Regeln sagen was durchgesetzt werden soll, dieses Skill zeigt wie.

Die unten genannten Bibliotheken (NativeWind, Zustand/Jotai, TanStack Query) sind gängige, etablierte Optionen, die zur Veranschaulichung gezeigt werden – die Muster sind wichtiger als das spezifische Paket, und jedes Äquivalent funktioniert. Zod wird für die Validierung verwendet, um Konsistenz mit den bestehenden typescript/-Regeln von ECC zu gewährleisten.

Diese Muster setzen den verwalteten Expo-Workflow (Expo Router, EAS, expo-* Module) auf der Neuen Architektur voraus (Standard in aktuellen Expo SDKs, ab SDK 55+ obligatorisch). Sie nehmen NICHT das Browser-DOM an – React Native hat kein <div>, keine URL-Leiste und keine Standard-Web-Datenabruf-Funktionen.

Wann aktivieren

Verwenden Sie dieses Skill, wenn:

  • React Native / Expo Screens, Komponenten oder Navigation erstellt oder bearbeitet werden
  • Routing mit Expo Router (dateibasiertes app/-Verzeichnis) eingerichtet wird
  • Entscheidungen getroffen werden, wo Zustand hingehört (Server-Cache vs. Client-Store vs. Routenparameter vs. Formular)
  • Datenabruf mit TanStack Query und Validierung der Antworten mit Zod verbunden wird
  • Lange oder schwere Listen gerendert werden
  • Ein Styling-Ansatz ausgewählt oder angewendet wird (NativeWind oder StyleSheet)
  • Native Geräte-APIs (Kamera, Standort, Benachrichtigungen) oder sicherer Speicher verwendet werden
  • RN-Code auf mobilspezifische Probleme überprüft wird

Verwenden Sie NICHT die Web/React-DOM-Muster hier – URL-als-Zustand, <div> und SWR-für-Browser gelten nicht für React Native.

Kernkonzepte

Projektstruktur (Expo Router)

Dateibasiertes Routing unter app/. Halten Sie Routendateien schlank: Sie lesen und validieren Parameter und delegieren dann an eine Screen-Komponente, die in components/ oder features/ lebt.

app/
  _layout.tsx          # Root Stack
  (tabs)/
    _layout.tsx        # Tab-Navigator
    index.tsx          # Home
  user/[id].tsx        # dynamische Route
components/
features/
  user/UserProfile.tsx

Navigation: Routenparameter validieren

Deep Links und dynamische Routen liefern nicht vertrauenswürdige Zeichenketten. Validieren Sie sie vor der Verwendung mit Zod.

// app/user/[id].tsx
import { useLocalSearchParams, router } from 'expo-router'
import { z } from 'zod'
import { UserProfile } from '@/features/user/UserProfile'

const Params = z.object({ id: z.string().uuid() })

export default function UserRoute() {
  const parsed = Params.safeParse(useLocalSearchParams())
  if (!parsed.success) {
    router.replace('/not-found')
    return null
  }
  return <UserProfile userId={parsed.data.id} />
}

Zustand: Belange getrennt halten

Duplizieren Sie keine Serverdaten in einen Client-Store. Jeder Belang hat sein eigenes Zuhause.

BelangÜbliche Wahlmöglichkeiten
Serverzustand (entfernte Daten)eine Server-Cache-Bibliothek (TanStack Query, SWR)
Client/UI-Zustandein leichter Store (Zustand, Jotai) oder Context
Routen-/NavigationszustandExpo Router Parameter
Formularzustandeine Formularbibliothek (z. B. React Hook Form) + Schema-Validierung
Geheimnisse / Tokensexpo-secure-store
Nicht-geheime PersistenzAsyncStorage / MMKV

Bevorzugen Sie lokales useState, bis Zustand wirklich geteilt werden muss.

Datenabruf: eine Cache-Bibliothek + Zod

Verwenden Sie eine Server-Cache-Bibliothek (TanStack Query, SWR) anstelle von fetch-in-useEffect. Validieren Sie an der Grenze und leiten Sie Typen aus dem Schema ab. Behandeln Sie Lade-, Fehler- und Leerzustände explizit. (Beispiel verwendet TanStack Query.)

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

const User = z.object({ id: z.string(), email: z.string().email() })
type User = z.infer<typeof User>

export function useUser(id: string) {
  return useQuery({
    queryKey: ['user', id],
    queryFn: async (): Promise<User> => User.parse(await api.getUser(id)),
  })
}

export function useUpdateEmail(id: string) {
  const qc = useQueryClient()
  return useMutation({
    mutationFn: (email: string) => api.updateEmail(id, email),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['user', id] }),
  })
}

Listen: virtualisieren, niemals ein großes Array in einer ScrollView mappen

import { FlatList } from 'react-native'

<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={renderItem}          // memoisiert
  initialNumToRender={10}
  windowSize={5}
/>

Verwenden Sie FlashList (Shopify) für große oder heterogene Listen.

Styling: ein System auswählen

StyleSheet.create() ist die framework-native Option; Utility-Class-Bibliotheken (z. B. NativeWind) sind eine gängige Alternative. Wählen Sie eines und bleiben Sie konsistent. Bauen Sie Style-Objekte niemals inline in JSX auf heißen Pfaden.

// NativeWind
<View className="p-4 rounded-2xl bg-white">
  <Text className="text-base font-semibold">Hallo</Text>
</View>

// StyleSheet
const styles = StyleSheet.create({ card: { padding: 16, borderRadius: 16, backgroundColor: '#fff' } })
<View style={styles.card}>...</View>

Native APIs: in Hooks einkapseln, Effekte bereinigen

Halten Sie Expo SDK-Aufrufe und Abonnements in use*-Hooks, nicht in JSX. Bereinigen Sie immer.

import { useEffect, useState } from 'react'
import * as Location from 'expo-location'

type LocationState =
  | { status: 'loading' }
  | { status: 'denied' }
  | { status: 'granted'; coords: Location.LocationObjectCoords }

export function useCurrentLocation() {
  // Status verfolgen, nicht nur Koordinaten – damit die UI unterscheiden kann
  // zwischen "wird noch geladen" und "Berechtigung verweigert" und eine umsetzbare Nachricht anzeigen kann.
  const [state, setState] = useState<LocationState>({ status: 'loading' })

  useEffect(() => {
    let active = true
    ;(async () => {
      const { status } = await Location.requestForegroundPermissionsAsync()
      if (status !== 'granted') {
        if (active) setState({ status: 'denied' })
        return
      }
      const pos = await Location.getCurrentPositionAsync({})
      if (active) setState({ status: 'granted', coords: pos.coords })
    })()
    return () => { active = false }   // altes Ergebnis nach Unmount ignorieren
  }, [])

  return state
}

Sicheres Speichern für Tokens

import * as SecureStore from 'expo-secure-store'

await SecureStore.setItemAsync('auth_token', token)   // Keychain / Keystore
const token = await SecureStore.getItemAsync('auth_token')

Codebeispiele

Ein vollständiger Screen: Route → Query → Liste → Zustände

// app/(tabs)/orders.tsx
import { memo, useCallback } from 'react'
import { FlatList, Text, View } from 'react-native'
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'

const OrderSchema = z.object({ id: z.string(), total: z.number(), status: z.string() })
const OrdersSchema = z.array(OrderSchema)
type Order = z.infer<typeof OrderSchema>

function useOrders() {
  return useQuery({
    queryKey: ['orders'],
    queryFn: async () => OrdersSchema.parse(await api.listOrders()),
  })
}

// Memoisiert, sodass die Referenz über Renderings hinweg stabil bleibt (siehe Listen-Richtlinien).
const OrderRow = memo(function OrderRow({ item }: { item: Order }) {
  return (
    <View className="px-4 py-3 border-b border-neutral-200">
      <Text className="font-medium">#{item.id}</Text>
      <Text className="text-neutral-500">{item.status} · ${item.total}</Text>
    </View>
  )
})

export default function OrdersScreen() {
  const { data, isLoading, isError, refetch, isRefetching } = useOrders()
  const renderItem = useCallback(({ item }: { item: Order }) => <OrderRow item={item} />, [])

  if (isLoading) return <Centered><Text>Laden…</Text></Centered>
  if (isError) return <Centered><Text accessibilityRole="alert">Bestellungen konnten nicht geladen werden.</Text></Centered>
  if (!data?.length) return <Centered><Text>Noch keine Bestellungen.</Text></Centered>

  return (
    <FlatList
      data={data}
      keyExtractor={(o) => o.id}
      onRefresh={refetch}
      refreshing={isRefetching}
      renderItem={renderItem}
    />
  )
}

Ein Formular: React Hook Form + Zod Resolver

import { useForm, Controller } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { TextInput, Button, Text } from 'react-native'

const Schema = z.object({ email: z.string().email('Ungültige E-Mail') })
type FormValues = z.infer<typeof Schema>

export function EmailForm({ onSubmit }: { onSubmit: (v: FormValues) => void }) {
  const { control, handleSubmit, formState: { errors } } = useForm<FormValues>({
    resolver: zodResolver(Schema),
    defaultValues: { email: '' },
  })

  return (
    <>
      <Controller
        control={control}
        name="email"
        render={({ field: { value, onChange, onBlur } }) => (
          <TextInput
            value={value}
            onChangeText={onChange}
            onBlur={onBlur}
            autoCapitalize="none"
            keyboardType="email-address"
            accessibilityLabel="E-Mail-Adresse"
          />
        )}
      />
      {errors.email && <Text accessibilityRole="alert">{errors.email.message}</Text>}
      <Button title="Speichern" onPress={handleSubmit(onSubmit)} />
    </>
  )
}

Anti-Patterns

// FALSCH: großes Array in einer ScrollView gemappt (keine Virtualisierung, ruckelig, hoher Speicher)
<ScrollView>{items.map((i) => <Row key={i.id} item={i} />)}</ScrollView>
// RICHTIG: FlatList / FlashList

// FALSCH: Serverdaten in einen Client-Store kopiert (zwei Quellen der Wahrheit, veraltete Daten)
const useStore = create((set) => ({ users: [], setUsers: (u) => set({ users: u }) }))
useEffect(() => { getUsers().then(setUsers) }, [])
// RICHTIG: useQuery besitzt den Serverzustand; leiten Sie ab, was Sie benötigen

// FALSCH: Tokens in AsyncStorage (nicht verschlüsselt)
await AsyncStorage.setItem('auth_token', token)
// RICHTIG: expo-secure-store

// FALSCH: Deep-Link-Parametern vertrauen
const { id } = useLocalSearchParams(); fetchUser(id)
// RICHTIG: vor der Verwendung mit Zod validieren

// FALSCH: Inline-Style-Objekt, das bei jedem Rendern auf einem heißen Pfad neu erstellt wird
<View style={{ padding: 16, backgroundColor: '#fff' }} />
// RICHTIG: StyleSheet.create im Modulbereich oder NativeWind className

// FALSCH: Echtes Geheimnis im Bundle ausgeliefert
const STRIPE_SECRET = 'sk_live_...'
// RICHTIG: Privilegierte Aufrufe serverseitig lassen; nur öffentliche Schlüssel ausliefern, die durch Backend-Regeln geschützt sind

Best Practices

  • Halten Sie Routendateien schlank; legen Sie Logik in Screen-Komponenten und use*-Hooks.
  • Validieren Sie jede externe Eingabe (API-Antworten, Routenparameter, Push-Payloads) mit Zod.
  • Lassen Sie TanStack Query den Serverzustand verwalten; halten Sie Client-Stores klein.
  • Rendern Sie immer Lade-, Fehler- und Leerzustände – niemals nur einen Spinner ohne Fallback.
  • Virtualisieren Sie Listen; memoieren Sie renderItem; stellen Sie einen stabilen keyExtractor bereit.
  • Verwenden Sie react-native-reanimated für Animationen (UI-Thread); vermeiden Sie schwere Arbeit auf dem JS-Thread.
  • Speichern Sie Tokens in expo-secure-store; vertrauen Sie dem Client niemals für die Autorisierung.
  • Respektieren Sie Safe Areas, Dynamic Type und Barrierefreiheitsrollen/-Labels von Anfang an.
  • Bestätigen Sie die Kompatibilität mit der Neuen Architektur für jede native Abhängigkeit vor der Veröffentlichung.

Verwandte Skills

  • frontend-patterns – React/Next.js (Web)-Muster; nützlich für gemeinsame React-Konzepte, aber DOM-spezifisch.
  • coding-standards – TypeScript/JavaScript-Idiome, die auf RN-Code anwendbar sind.
  • tdd-workflow, e2e-testing – Testprozess (Jest + React Native Testing Library, Maestro/Detox für RN).
  • security-review – Allgemeine Sicherheitscheckliste, die die RN-Bundle-/Geheimnis-Richtlinien oben ergänzt.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills