mobile-developer

安装量: 207
排名: #4203

安装

npx skills add https://github.com/daffy0208/ai-dev-standards --skill mobile-developer

Mobile Developer Skill

I help you build cross-platform mobile apps with React Native and Expo.

What I Do

App Development:

React Native / Expo apps (iOS + Android) Navigation and routing State management API integration

Native Features:

Camera, location, notifications Biometric authentication File system access Device sensors

Performance:

Optimize bundle size Lazy loading Image optimization Memory management

Distribution:

App Store / Google Play submission Over-the-air (OTA) updates Beta testing (TestFlight, internal testing) Quick Start: Expo App Create New App

Create Expo app

npx create-expo-app my-app --template blank-typescript

cd my-app

Install dependencies

npx expo install react-native-screens react-native-safe-area-context npx expo install expo-router

Start development

npx expo start

Project Structure my-app/ ├── app/ │ ├── (tabs)/ │ │ ├── index.tsx # Home tab │ │ ├── profile.tsx # Profile tab │ │ └── _layout.tsx # Tab layout │ ├── users/ │ │ └── [id].tsx # Dynamic route │ ├── _layout.tsx # Root layout │ └── +not-found.tsx # 404 page ├── components/ │ ├── Button.tsx │ ├── Card.tsx │ └── Loading.tsx ├── hooks/ │ └── useAuth.ts ├── app.json └── package.json

Navigation with Expo Router Tab Navigation // app/(tabs)/_layout.tsx import { Tabs } from 'expo-router' import { Ionicons } from '@expo/vector-icons'

export default function TabLayout() { return ( ( ) }} /> ( ) }} /> ) }

Stack Navigation // app/users/[id].tsx import { useLocalSearchParams } from 'expo-router' import { View, Text } from 'react-native'

export default function UserDetail() { const { id } = useLocalSearchParams()

return ( User ID: {id} ) }

UI Components Custom Button // components/Button.tsx import { TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native'

interface ButtonProps { title: string onPress: () => void variant?: 'primary' | 'secondary' loading?: boolean disabled?: boolean }

export function Button({ title, onPress, variant = 'primary', loading = false, disabled = false }: ButtonProps) { return ( {loading ? ( ) : ( {title} )} ) }

const styles = StyleSheet.create({ button: { padding: 16, borderRadius: 8, alignItems: 'center', justifyContent: 'center' }, primary: { backgroundColor: '#007AFF' }, secondary: { backgroundColor: '#8E8E93' }, disabled: { opacity: 0.5 }, text: { color: '#fff', fontSize: 16, fontWeight: '600' } })

Card Component // components/Card.tsx import { View, Text, StyleSheet, TouchableOpacity } from 'react-native' import { ReactNode } from 'react'

interface CardProps { title?: string children: ReactNode onPress?: () => void }

export function Card({ title, children, onPress }: CardProps) { const Container = onPress ? TouchableOpacity : View

return ( {title && {title}} {children} ) }

const styles = StyleSheet.create({ card: { backgroundColor: '#fff', borderRadius: 12, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3 }, title: { fontSize: 18, fontWeight: '600', marginBottom: 12 } })

Data Fetching Custom Hook // hooks/useQuery.ts import { useState, useEffect } from 'react'

interface UseQueryResult { data: T | null loading: boolean error: Error | null refetch: () => void }

export function useQuery(url: string): UseQueryResult { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null)

const fetchData = async () => { try { setLoading(true) const response = await fetch(url)

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
  }

  const json = await response.json()
  setData(json)
  setError(null)
} catch (e) {
  setError(e as Error)
} finally {
  setLoading(false)
}

}

useEffect(() => { fetchData() }, [url])

return { data, loading, error, refetch: fetchData } }

Usage // app/(tabs)/index.tsx import { View, Text, FlatList, RefreshControl } from 'react-native' import { useQuery } from '@/hooks/useQuery' import { Card } from '@/components/Card'

interface Post { id: string title: string content: string }

export default function HomeScreen() { const { data, loading, error, refetch } = useQuery( 'https://api.example.com/posts' )

if (error) { return ( Error: {error.message} ) }

return ( item.id} renderItem={({ item }) => ( {item.content} )} refreshControl={ } /> ) }

Native Features Camera // app/camera.tsx import { Camera, CameraType } from 'expo-camera' import { useState } from 'react' import { Button, View, StyleSheet } from 'react-native'

export default function CameraScreen() { const [type, setType] = useState(CameraType.back) const [permission, requestPermission] = Camera.useCameraPermissions()

if (!permission) { return }

if (!permission.granted) { return (

返回排行榜