Claude Code und React Native: Praxisguide für Expo, Native und Release
Claude Code mit React Native nutzen: Expo vs bare, Berechtigungen, Metro-Fehler, Emulatoren, A11y und Release-Checks.
Vor dem Coding die mobile Grenze festlegen
Claude Code ist in React Native nicht nur deshalb nützlich, weil es schneller eine View schreibt. Der eigentliche Vorteil ist, dass es das Projekt lesen, TypeScript ändern, Prüfkommandos ausführen, native Rebuilds erklären und am Ende eine überprüfbare Übergabe liefern kann. Mobile Entwicklung hat mehr Grenzen als eine Web-Komponente: iOS-Berechtigungen, Android package, Metro-Auflösung, development builds, Emulatoren, Barrierefreiheit und Release-Prüfungen.
Die schwache Anfrage lautet: “Baue eine React-Native-App.” Die bessere Anfrage sagt zuerst, ob es eine Expo-App, ein Expo development build oder ein bare React Native Projekt mit eigenen ios/- und android/-Ordnern ist. Sie nennt außerdem erlaubte Dateien, Kommandos mit Rückfrage und die Plattform, die getestet werden muss.
Als offizielle Grundlage nutze ich Claude Code overview, Claude Code permissions, Expo Documentation, Expo development builds, React Native environment setup, React Native Native Modules, Metro troubleshooting und React Native accessibility. Wenn Claude Code neu im Team ist, lies zuerst den Claude Code Einstieg und danach den Berechtigungs-Guide.
Mit einer project map starten
Eine project map ist eine kurze Betriebsanleitung für den Agenten. Harness bedeutet hier der Arbeitsrahmen des Agenten: wo Claude Code arbeiten darf, wie Erfolg geprüft wird und welche Aktionen nicht automatisch laufen sollen. Ohne diese Karte kann Claude Code funktionierenden Code erzeugen, aber native Rebuilds, Plattformunterschiede oder Release-Grenzen übersehen.
flowchart LR
A["Project map"] --> B["Claude Code task"]
B --> C["JS/TS implementation"]
B --> D["Native config"]
C --> E["Metro and unit tests"]
D --> F["Dev build / emulator"]
E --> G["Accessibility check"]
F --> G
G --> H["Release checklist"]
Vor der Implementierung reicht eine kleine Datei:
# React Native task map
App type: Expo app using TypeScript and Expo Router.
Native runtime: Expo Go for pure JS changes, development build for native libraries.
Targets: Android emulator first, iOS simulator on macOS before release.
Allowed files: app/, components/, hooks/, app.config.ts, metro.config.js, __tests__/.
Do not change: package manager, app slug, bundle identifiers, signing files, .env files.
Verification: npm run lint, npm test, npx expo-doctor, Android emulator smoke test.
Handoff: list changed files, commands run, platform not tested, and any native rebuild needed.
Aktuelle Expo-Templates können Kontext für Coding Agents enthalten. Bestehende Apps haben aber oft alte READMEs, alte SDK-Annahmen oder undokumentierte native Einstellungen. Lasse Claude Code deshalb immer zuerst das echte Repository lesen.
Expo oder bare React Native bewusst wählen
Die React-Native-Dokumentation unterscheidet Framework-basierte Entwicklung von direktem Setup mit Android Studio und Xcode. In der Praxis ist Expo für neue Apps meist der schnellste Weg. Bare React Native bleibt sinnvoll, wenn native SDKs, komplexe Gradle-Konfiguration, Pods oder Anbieter-Vorgaben existieren.
| Entscheidung | Expo passt besser | Bare React Native passt besser |
|---|---|---|
| Startgeschwindigkeit | MVPs, interne Tools, Lernen, Expo-SDK reicht aus | Bestehender iOS/Android-Code muss bleiben |
| Native Funktionen | Camera, SecureStore, Notifications und config plugins | Eigenes SDK, Payment-Terminal, spezielles Bluetooth, tiefe Build-Anpassung |
| Claude-Code-Scope | app/, components/, app.config.ts, Tests | ios/, android/, Codegen, Pods, Gradle, generierte Dateien |
| Prüfung | Expo Go oder development build, npx expo-doctor | npm run android, pod install, Xcode/Android Studio |
Expo Go ist kein Release-Beweis. Expo beschreibt es als schnelle Umgebung mit festem Satz nativer Bibliotheken. Sobald du eine Library mit nativem Code hinzufügst, brauchst du ein development build und Claude Code soll melden, dass ein neues Binary nötig ist.
Ein sauberes Expo-Testprojekt startest du so:
npx create-expo-app@latest rn-claude-lab
cd rn-claude-lab
npx expo install expo-camera expo-secure-store @react-native-community/netinfo
npm install --save-dev @testing-library/react-native jest-expo @types/jest
npx expo start
Für Android Emulator drückst du a, für iOS Simulator auf macOS i. Wenn das Netzwerk blockiert, hilft npx expo start --tunnel, ist aber langsamer als LAN oder Emulator.
Claude-Code-Berechtigungen mobil einschränken
In React Native kann ein einzelnes Kommando einen großen Diff erzeugen. expo prebuild, pod install, gradlew clean und eas build sind legitim, aber sie sollten nicht still während einer kleinen UI-Änderung laufen.
Claude Code permissions trennen allow, ask und deny. Eine gemeinsame .claude/settings.json kann sichere Checks erlauben, bei nativer Regeneration und Release-Builds fragen und Secrets sowie Push-Kommandos blockieren.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npx expo-doctor)",
"Bash(adb devices)"
],
"ask": [
"Edit",
"Bash(npx expo prebuild*)",
"Bash(eas build*)",
"Bash(cd ios && bundle exec pod install)"
],
"deny": [
"Read(.env)",
"Read(.env.local)",
"Bash(git push*)",
"Bash(rm -rf*)"
]
}
}
Das ist kein Misstrauen gegenüber dem Tool. Es hält mobile Seiteneffekte überprüfbar. Wenn ein nativer Rebuild nötig ist, soll Claude Code den Grund zuerst nennen.
Einen Screen mit Kamera-Berechtigung bauen
Der erste praktische Fall ist ein QR-Scanner für Check-in, Inventar oder interne Tools. Expo Camera stellt CameraView und useCameraPermissions bereit. Bitte Claude Code, drei Zustände zu modellieren: Permission lädt, Permission fehlt, Kamera bereit. Dazu gehören Accessibility-Labels und Schutz gegen doppelte Scans.
// components/CameraQrCheck.tsx
import { CameraView, useCameraPermissions } from 'expo-camera';
import { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
type ScanResult = {
data: string;
type: string;
} | null;
export function CameraQrCheck() {
const [permission, requestPermission] = useCameraPermissions();
const [scan, setScan] = useState<ScanResult>(null);
if (!permission) {
return (
<View style={styles.center}>
<Text>Checking camera permission...</Text>
</View>
);
}
if (!permission.granted) {
return (
<View style={styles.center}>
<Text style={styles.title}>Camera access is required</Text>
<Text style={styles.body}>
Allow camera access to scan QR codes on this device.
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="Allow camera access"
disabled={!permission.canAskAgain}
onPress={requestPermission}
style={({ pressed }) => [
styles.button,
pressed && styles.buttonPressed,
!permission.canAskAgain && styles.buttonDisabled,
]}
>
<Text style={styles.buttonText}>Allow camera</Text>
</Pressable>
</View>
);
}
return (
<View style={styles.container}>
<CameraView
style={styles.camera}
barcodeScannerSettings={{ barcodeTypes: ['qr'] }}
onBarcodeScanned={
scan
? undefined
: ({ data, type }) => {
setScan({ data, type });
}
}
/>
<View style={styles.result}>
<Text accessibilityLiveRegion="polite" style={styles.title}>
{scan ? `Scanned ${scan.type}` : 'Point the camera at a QR code'}
</Text>
{scan ? <Text selectable>{scan.data}</Text> : null}
{scan ? (
<Pressable
accessibilityRole="button"
accessibilityLabel="Scan another QR code"
onPress={() => setScan(null)}
style={styles.button}
>
<Text style={styles.buttonText}>Scan again</Text>
</Pressable>
) : null}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#111827' },
center: { flex: 1, justifyContent: 'center', gap: 12, padding: 24 },
camera: { flex: 1 },
result: { gap: 12, padding: 16, backgroundColor: '#f9fafb' },
title: { fontSize: 18, fontWeight: '700', color: '#111827' },
body: { fontSize: 15, lineHeight: 22, color: '#374151' },
button: {
alignItems: 'center',
borderRadius: 8,
backgroundColor: '#2563eb',
paddingHorizontal: 16,
paddingVertical: 12,
},
buttonPressed: { opacity: 0.75 },
buttonDisabled: { backgroundColor: '#9ca3af' },
buttonText: { color: '#ffffff', fontWeight: '700' },
});
Die Komponente ist nach Installation von expo-camera kopierbar. Permission-Texte und native Einstellungen gehören in die App-Konfiguration, weil manche Änderungen einen neuen nativen Build brauchen.
// app.config.ts
import type { ConfigContext, ExpoConfig } from 'expo/config';
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: config.name ?? 'rn-claude-lab',
slug: config.slug ?? 'rn-claude-lab',
ios: {
...config.ios,
bundleIdentifier: 'com.example.rnclaudelab',
infoPlist: {
...config.ios?.infoPlist,
NSCameraUsageDescription: 'Scan QR codes for check-in.',
},
},
android: {
...config.android,
package: 'com.example.rnclaudelab',
permissions: ['CAMERA'],
},
plugins: ['expo-camera'],
});
Expo config plugins wenden solche Einstellungen in prebuild- und nativen Build-Flows an. Die wichtige Anweisung lautet: “Wenn du app.config.ts änderst, melde, ob ein development build nötig ist.”
Metro-Fehler als Beweise behandeln
Der zweite Fall ist Unable to resolve module, besonders in Monorepos. Die offizielle Metro-Troubleshooting-Seite nennt Cache Reset, aber Cache Reset ersetzt keine Ursachenanalyse.
Gib Claude Code den vollständigen Fehler, das Kommando, den Package Manager, die Workspace-Struktur und die letzte Datei-Verschiebung. Eine Expo-App im Workspace kann so eine Konfiguration brauchen:
// metro.config.js
const path = require('path');
const { getDefaultConfig } = require('expo/metro-config');
const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, '..');
const config = getDefaultConfig(projectRoot);
config.watchFolders = [workspaceRoot];
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(workspaceRoot, 'node_modules'),
];
module.exports = config;
Nicht blind hinzufügen. Eine normale Expo-App in einem Paket braucht das meist nicht. Claude Code soll erklären, warum watchFolders nötig ist, und es weglassen, wenn die Ursache Groß-/Kleinschreibung, fehlende Dependency, Babel oder ein falscher Import ist.
Native Module erst planen, dann nativ ändern
Der dritte Fall ist die Anbindung eines Vendor-SDKs oder einer Plattform-API. Die aktuelle Native-Modules-Dokumentation konzentriert sich auf Turbo Native Modules und Codegen. Eine gute Aufgabe beginnt deshalb mit der TypeScript-Schnittstelle und geht erst danach zu Android und iOS.
Wenn Expo Camera, SecureStore oder NetInfo reichen, schreibe kein eigenes Native Module. Bei Payment-Terminals, speziellem Bluetooth oder internem Auth-SDK fragst du zuerst nach einem Plan.
Implement a native bridge plan, not the full code yet.
Goal: expose a device serial reader to TypeScript.
First output:
1. TypeScript interface and error model.
2. Android/iOS files that would need edits.
3. Build commands for each platform.
4. Risks: permissions, threading, simulator limitations, release signing.
Do not edit ios/ or android/ until the plan is reviewed.
Das wirkt am Anfang langsamer, reduziert aber Review-Aufwand. Kotlin, Swift, Pods und Gradle brauchen klare Grenzen.
Tests und Barrierefreiheit in dieselbe Aufgabe legen
React-Native-Accessibility-APIs versorgen VoiceOver und TalkBack. Wenn eine View zugänglich sein soll, sind Label und Role Teil der Implementierung.
Beginne mit dem Test für den Zustand ohne Berechtigung:
// __tests__/CameraQrCheck.test.tsx
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react-native';
import { CameraQrCheck } from '../components/CameraQrCheck';
const mockRequestPermission = jest.fn();
jest.mock('expo-camera', () => ({
CameraView: 'CameraView',
useCameraPermissions: () => [
{ granted: false, canAskAgain: true },
mockRequestPermission,
],
}));
describe('CameraQrCheck', () => {
beforeEach(() => {
mockRequestPermission.mockClear();
});
it('requests camera permission from the empty state', () => {
render(<CameraQrCheck />);
fireEvent.press(screen.getByText('Allow camera'));
expect(mockRequestPermission).toHaveBeenCalledTimes(1);
});
});
Danach prüfst du auf Gerät oder Emulator: Permission Dialog, Ablehnungsweg, Rotation, Scan bei wenig Licht und Screenreader-Labels. Der Handoff muss sagen, welche Plattform getestet wurde. “Android emulator passed, iOS not tested” ist nützlich. “looks good” ist es nicht.
Release-Checks als Kommandos festhalten
Dev Menu und LogBox sind Entwicklungstools; Release-Builds verhalten sich anders. Claude Code soll Kommando-Evidenz zurückgeben.
npm run lint
npm test -- --runInBand
npx expo-doctor
npx expo start -c
adb devices
adb shell input keyevent 82
npx expo run:android
# macOS only:
npx expo run:ios
Mit EAS Build bleiben development, preview und production getrennt. Claude Code darf bundle identifiers, Android package, signing files oder production profile nur ändern, wenn die Aufgabe es ausdrücklich verlangt.
Praxisfälle und typische Fehler
Fall eins ist ein neues Expo-MVP. Login, QR-Scan, sichere lokale Speicherung, einfache API und ein interner Ablauf lassen sich in Screens, Hooks, Tests und Config teilen. Wenn Umsatz eine Rolle spielt, gehören Analytics und CTA-Verhalten in die Definition of Done.
Fall zwei ist eine bestehende bare React Native App. Metro-Fehler, Android-only Crash, iOS-Permission-Text und native SDK-Upgrades sind gute Claude-Code-Aufgaben, wenn du Fehlerklassifikation, minimalen Diff und Rebuild-Hinweis verlangst.
Fall drei ist Recherche vor nativer SDK-Integration. Payment, Gesundheitsdaten, Bluetooth und Enterprise Auth brauchen zuerst eine Tabelle mit OS-Support, Permissions, Store-Review-Risiko, Simulator-Grenzen und Testgeräten. Kombiniere das mit der Review Workflow Checklist und dem TDD Guide.
Die Fehler wiederholen sich: Expo Go ist kein Release-Beweis, Cache Reset ist keine Ursachenanalyse, Plattformtests dürfen nicht bis zum Ende warten, Accessibility-Labels sind kein Nachtrag, und native Build-Kommandos brauchen einen Grund.
CTA: Den Mobile-Workflow als Template nutzen
In React Native bringen wiederverwendbare project map, permissions file, verification commands und review checklist am meisten. Einzelentwickler starten mit dem kostenlosen Cheatsheet. Für wiederverwendbare Prompts und Setup-Material lohnt sich ein Blick auf ClaudeCodeLab products. Teams, die Expo/bare React Native Regeln, CI, Release Gates und Training auf ein echtes Repository anwenden wollen, nutzen Claude Code training and consultation.
Als Vergleich helfen der Claude Code React Guide und der Flutter/Dart Guide.
Nach dem praktischen Test dieses Workflows waren für Masa drei Gewohnheiten am wichtigsten: vor der Implementierung Expo oder bare entscheiden, bei Änderungen an app.config.ts eine development-build-Notiz verlangen und Berechtigungen sowie Metro zuerst im Android Emulator prüfen. Bei Camera und SecureStore zählt die Verifikationsgrenze mehr als die Geschwindigkeit der Codegenerierung.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.