Builds, optimizes, and debugs cross-platform mobile applications with React Native and Expo. Implements navigation hierarchies (tabs, stacks, drawers), configures native modules, optimizes FlatList rendering with memo and useCallback, and handles platform-specific code for iOS and Android. Use when building a React Native or Expo mobile app, setting up navigation, integrating native modules, improving scroll performance, handling SafeArea or keyboard input, or configuring Expo SDK projects.
95
100%
Does it follow best practices?
Impact
90%
1.26xAverage score across 6 eval scenarios
Passed
No known issues
Senior mobile engineer building production-ready cross-platform applications with React Native and Expo.
npx expo doctor to verify environment and SDK compatibility; fix any reported issues before proceedingnpx expo start --clear, then restartnpx expo run:iosadb logcat or Gradle output → resolve SDK/NDK version mismatch → rebuild with npx expo run:androidnpx expo install <module> to ensure compatible version, then rebuild native layersLoad detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Navigation | references/expo-router.md | Expo Router, tabs, stacks, deep linking |
| Platform | references/platform-handling.md | iOS/Android code, SafeArea, keyboard |
| Lists | references/list-optimization.md | FlatList, performance, memo |
| Storage | references/storage-hooks.md | AsyncStorage, MMKV, persistence |
| Structure | references/project-structure.md | Project setup, architecture |
import React, { memo, useCallback } from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
type Item = { id: string; title: string };
const ListItem = memo(({ title, onPress }: { title: string; onPress: () => void }) => (
<View style={styles.item}>
<Text onPress={onPress}>{title}</Text>
</View>
));
export function ItemList({ data }: { data: Item[] }) {
const handlePress = useCallback((id: string) => {
console.log('pressed', id);
}, []);
const renderItem = useCallback(
({ item }: { item: Item }) => (
<ListItem title={item.title} onPress={() => handlePress(item.id)} />
),
[handlePress]
);
return (
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={renderItem}
removeClippedSubviews
maxToRenderPerBatch={10}
windowSize={5}
/>
);
}
const styles = StyleSheet.create({
item: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth },
});import React from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
TextInput,
StyleSheet,
SafeAreaView,
} from 'react-native';
export function LoginForm() {
return (
<SafeAreaView style={styles.safe}>
<KeyboardAvoidingView
style={styles.flex}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
<TextInput style={styles.input} placeholder="Email" autoCapitalize="none" />
<TextInput style={styles.input} placeholder="Password" secureTextEntry />
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1 },
flex: { flex: 1 },
content: { padding: 16, gap: 12 },
input: { borderWidth: 1, borderRadius: 8, padding: 12, fontSize: 16 },
});import { Platform, StyleSheet, View, Text } from 'react-native';
export function StatusChip({ label }: { label: string }) {
return (
<View style={styles.chip}>
<Text style={styles.label}>{label}</Text>
</View>
);
}
const styles = StyleSheet.create({
chip: {
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 999,
backgroundColor: '#0a7ea4',
// Platform-specific shadow
...Platform.select({
ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.2, shadowRadius: 4 },
android: { elevation: 3 },
}),
},
label: { color: '#fff', fontSize: 13, fontWeight: '600' },
});When implementing React Native features, deliver:
Platform.select or .ios.tsx / .android.tsx splits as neededReact Native 0.73+, Expo SDK 50+, Expo Router, React Navigation 7, Reanimated 3, Gesture Handler, AsyncStorage, MMKV, React Query, Zustand
5b76101
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.