AI Skill Library

React Native Basics

Core components, styling, navigation, platform differences, Expo workflow.

react-nativemobileiosandroid
# React Native Basics

## Create (Expo recommended)
```bash
npx create-expo-app@latest MyApp --template
npx expo start   # QR code -> Expo Go app
```

## Core components
```tsx
import { View, Text, TextInput, Image, ScrollView,
         FlatList, TouchableOpacity, Pressable,
         StyleSheet, Platform, Dimensions } from 'react-native'

// View = div, Text = p/span, Image = img
export default function Screen() {
  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>Hello</Text>
      <TextInput
        placeholder="Type here"
        value={text}
        onChangeText={setText}
        keyboardType="email-address"
        autoCapitalize="none"
      />
      <Pressable
        onPress={handlePress}
        style={({ pressed }) => [styles.btn, pressed && styles.pressed]}
      >
        <Text>Press me</Text>
      </Pressable>
    </ScrollView>
  )
}
```

## StyleSheet (no CSS cascade)
```ts
const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#fff', padding: 16 },
  title: { fontSize: 24, fontWeight: 'bold', color: '#000' },
  btn: { backgroundColor: '#000', padding: 12, borderRadius: 8 },
  pressed: { opacity: 0.7 },
})
// Flexbox default: column direction (unlike web's row)
// All dimensions are density-independent pixels (dp)
```

## FlatList (virtualized)
```tsx
<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <ItemCard item={item} />}
  numColumns={2}
  onEndReached={loadMore}
  onEndReachedThreshold={0.5}
  ListEmptyComponent={<Text>No items</Text>}
/>
```

## Navigation (Expo Router = file-based)
```tsx
// app/(tabs)/index.tsx  -> "/" tab
// app/(tabs)/profile.tsx -> "/profile" tab
// app/post/[id].tsx -> "/post/123"
import { useRouter, useLocalSearchParams } from 'expo-router'
const router = useRouter()
router.push('/profile')
router.push({ pathname: '/post/[id]', params: { id: '123' } })
const { id } = useLocalSearchParams()
```

## Platform differences
```ts
import { Platform } from 'react-native'
const style = { paddingTop: Platform.OS === 'ios' ? 44 : 24 }
Platform.select({ ios: 'iOS value', android: 'Android value', default: 'other' })
// Platform-specific files: Component.ios.tsx, Component.android.tsx
```

## Async storage
```bash
npx expo install @react-native-async-storage/async-storage
```
```ts
await AsyncStorage.setItem('key', JSON.stringify(value))
const raw = await AsyncStorage.getItem('key')
const value = raw ? JSON.parse(raw) : null
```

## Common Expo packages
- `expo-camera` -- camera access
- `expo-location` -- GPS
- `expo-notifications` -- push notifications
- `expo-image-picker` -- photo library
- `expo-haptics` -- vibration feedback
- `expo-secure-store` -- encrypted key-value store

API: /api/skills/react-native-basics