Claude-skill-registry Expo React Native Patterns
Common patterns for Expo SDK 54 and React Native development
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/expo-react-native" ~/.claude/skills/majiayu000-claude-skill-registry-expo-react-native-patterns && rm -rf "$T"
manifest:
skills/data/expo-react-native/SKILL.mdsource content
Expo React Native Patterns
Expo SDK 54 Setup
# Start dev server npx expo start # Run platform npm run android npm run ios # Clear cache npx expo start -c # Prebuild native npx expo prebuild --clean
Component Pattern
import React, { useState, useCallback } from 'react'; import { View, Text, Pressable, StyleSheet } from 'react-native'; interface Props { title: string; onPress: () => void; } export function MyComponent({ title, onPress }: Props) { const [loading, setLoading] = useState(false); const handlePress = useCallback(async () => { setLoading(true); await onPress(); setLoading(false); }, [onPress]); return ( <Pressable onPress={handlePress} style={styles.container}> <Text style={styles.text}>{title}</Text> </Pressable> ); } const styles = StyleSheet.create({ container: { padding: 16 }, text: { fontSize: 16 }, });
Expo Packages Used
| Package | Import | Usage |
|---|---|---|
| | Optimized images |
| | File operations |
| | Touch feedback |
| | Blur effects |
| | Gradients |
Image Component
import { Image } from 'expo-image'; <Image source={{ uri: imageUrl }} style={{ width: 120, height: 180 }} contentFit="cover" cachePolicy="memory-disk" placeholder={blurhash} transition={200} />
File System
import * as FileSystem from 'expo-file-system'; // Directories FileSystem.documentDirectory // Persistent storage FileSystem.cacheDirectory // Temporary cache // Operations await FileSystem.writeAsStringAsync(path, content); await FileSystem.readAsStringAsync(path); await FileSystem.deleteAsync(path, { idempotent: true }); await FileSystem.getInfoAsync(path); await FileSystem.makeDirectoryAsync(dir, { intermediates: true });
AsyncStorage
import AsyncStorage from '@react-native-async-storage/async-storage'; // Save await AsyncStorage.setItem('@key', JSON.stringify(data)); // Load const json = await AsyncStorage.getItem('@key'); const data = json ? JSON.parse(json) : defaultValue; // Remove await AsyncStorage.removeItem('@key');
Hooks Pattern
// Custom hook export function useDebounce<T>(value: T, delay: number): T { const [debounced, setDebounced] = useState(value); useEffect(() => { const timer = setTimeout(() => setDebounced(value), delay); return () => clearTimeout(timer); }, [value, delay]); return debounced; }
FlatList Optimization
<FlatList data={items} keyExtractor={(item) => item.id} renderItem={({ item }) => <ItemComponent item={item} />} numColumns={3} getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, })} removeClippedSubviews maxToRenderPerBatch={10} windowSize={5} />