# React Native: สร้างแอปมือถืออย่างสมบูรณ์ในปี 2026 > คู่มือฉบับสมบูรณ์สำหรับการพัฒนาแอปมือถือ iOS และ Android ด้วย React Native ตั้งแต่การติดตั้งสภาพแวดล้อมจนถึงการเผยแพร่ ครบทุกพื้นฐานที่จำเป็นสำหรับการเริ่มต้น - Published: 2026-01-10 - Updated: 2026-04-06 - Author: SharpSkill - Tags: react native, mobile development, javascript, ios, android - Reading time: 15 min --- React Native ช่วยให้สามารถสร้างแอปมือถือ native สำหรับ iOS และ Android จากโค้ดเบส JavaScript เพียงชุดเดียว ดูแลโดย Meta และถูกใช้งานในแอปอย่าง Instagram, Facebook และ Discord framework นี้มอบประสบการณ์การพัฒนาที่รวดเร็วพร้อมทั้งสร้างแอปที่มีประสิทธิภาพสูง > **ทำไมต้องเลือก React Native ในปี 2026?** > > ด้วยสถาปัตยกรรมใหม่ (Fabric และ TurboModules) ที่เสถียรแล้ว React Native มอบประสิทธิภาพใกล้เคียง native โดยยังคงผลิตภาพการพัฒนาระดับเว็บได้ มากกว่า 40% ของ 500 แอปชั้นนำใช้ React Native ## Development Environment Setup ก่อนเริ่มต้น การติดตั้งเครื่องมือที่จำเป็นเป็นขั้นตอนสำคัญ React Native มีสองแนวทางให้เลือก: Expo (แนะนำสำหรับผู้เริ่มต้น) และ React Native CLI (สำหรับการควบคุมที่ลึกซึ้งยิ่งขึ้น) ```bash # setup.sh # Node.js installation (LTS version recommended) # Check installed version node --version # >= 18.x required npm --version # >= 9.x required # Install Expo CLI tool globally npm install -g expo-cli # Create a new project with Expo npx create-expo-app@latest MyApp --template blank-typescript # Navigate to the project cd MyApp # Start the development server npx expo start ``` Expo ช่วยลดความซับซ้อนในการพัฒนาได้อย่างมากโดยจัดการการตั้งค่า native โดยอัตโนมัติ สำหรับการทดสอบแอป สามารถใช้แอป Expo Go บนสมาร์ทโฟนเพื่อสแกน QR code ที่แสดงบนหน้าจอ ```bash # structure.sh # Generated project structure MyApp/ ├── App.tsx # Application entry point ├── app.json # Expo configuration ├── package.json # Dependencies ├── tsconfig.json # TypeScript configuration ├── babel.config.js # Babel configuration └── assets/ # Images and resources ├── icon.png └── splash.png ``` ## Core React Native Components React Native มี component native ที่ใช้แทนองค์ประกอบ HTML แต่ละ component จะถูกแปลงโดยตรงเป็น component native บน iOS หรือ Android ```tsx // App.tsx import React from 'react'; import { View, Text, StyleSheet, SafeAreaView, StatusBar } from 'react-native'; // Main application component export default function App() { return ( // SafeAreaView prevents overlap with status bar {/* StatusBar configures system bar appearance */} {/* View is the equivalent of div */} {/* Text is required to display text */} Welcome to MyApp A React Native application ); } // StyleSheet.create optimizes styles for native const styles = StyleSheet.create({ container: { flex: 1, // Takes all available space backgroundColor: '#ffffff', }, header: { padding: 20, alignItems: 'center', // Centers horizontally justifyContent: 'center', // Centers vertically }, title: { fontSize: 24, fontWeight: 'bold', color: '#1a1a1a', marginBottom: 8, }, subtitle: { fontSize: 16, color: '#666666', }, }); ``` > **Flexbox เป็นค่าเริ่มต้น** > > React Native ใช้ Flexbox โดยมี `flexDirection: 'column'` เป็นค่าเริ่มต้น (ต่างจากเว็บที่ใช้ `row`) ความแตกต่างนี้สำคัญสำหรับการจัดวางเลย์เอาต์ ## Handling User Interactions การโต้ตอบแบบสัมผัสถูกจัดการผ่าน component เฉพาะทาง แต่ละประเภทการโต้ตอบมี component เฉพาะของตัวเองเพื่อประสิทธิภาพสูงสุด ```tsx // components/InteractiveButton.tsx import React, { useState } from 'react'; import { TouchableOpacity, TouchableHighlight, Pressable, Text, StyleSheet, View, } from 'react-native'; // Button component with different interaction styles export function InteractiveButton() { const [count, setCount] = useState(0); return ( {/* TouchableOpacity reduces opacity on touch */} setCount(c => c + 1)} > Counter: {count} {/* Pressable offers more control over states */} [ styles.button, styles.pressableButton, pressed && styles.buttonPressed, ]} onPress={() => console.log('Pressed!')} onLongPress={() => console.log('Long press!')} > {({ pressed }) => ( {pressed ? 'Pressed!' : 'Press here'} )} ); } const styles = StyleSheet.create({ container: { gap: 16, padding: 20, }, button: { backgroundColor: '#007AFF', paddingVertical: 14, paddingHorizontal: 28, borderRadius: 10, alignItems: 'center', }, pressableButton: { backgroundColor: '#34C759', }, buttonPressed: { backgroundColor: '#2DA44E', transform: [{ scale: 0.98 }], }, buttonText: { color: '#ffffff', fontSize: 16, fontWeight: '600', }, }); ``` ## Screen Navigation with React Navigation การนำทางเป็นสิ่งจำเป็นสำหรับทุกแอปมือถือ React Navigation เป็นโซลูชันมาตรฐานที่รองรับรูปแบบการนำทางหลากหลายประเภทที่เหมาะสมกับรูปแบบมือถือ ```bash # install-navigation.sh # Installing navigation dependencies npx expo install @react-navigation/native npx expo install @react-navigation/native-stack npx expo install react-native-screens react-native-safe-area-context ``` ```tsx // App.tsx import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; // Screen imports import { HomeScreen } from './screens/HomeScreen'; import { DetailScreen } from './screens/DetailScreen'; import { ProfileScreen } from './screens/ProfileScreen'; // Type definition for TypeScript navigation export type RootStackParamList = { Home: undefined; // No parameters Detail: { itemId: number; title: string }; // Required parameters Profile: { userId?: string }; // Optional parameter }; // Creating typed navigator const Stack = createNativeStackNavigator(); export default function App() { return ( // NavigationContainer manages navigation state ({ title: route.params.title })} /> ); } ``` ```tsx // screens/HomeScreen.tsx import React from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet } from 'react-native'; import { NativeStackScreenProps } from '@react-navigation/native-stack'; import { RootStackParamList } from '../App'; // Typing navigation props type Props = NativeStackScreenProps; // Sample data const ITEMS = [ { id: 1, title: 'First item' }, { id: 2, title: 'Second item' }, { id: 3, title: 'Third item' }, ]; export function HomeScreen({ navigation }: Props) { return ( {/* FlatList for performant lists */} item.id.toString()} renderItem={({ item }) => ( { // Navigation with typed parameters navigation.navigate('Detail', { itemId: item.id, title: item.title, }); }} > {item.title} )} ItemSeparatorComponent={() => } /> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, item: { backgroundColor: '#ffffff', padding: 20, }, itemText: { fontSize: 16, color: '#1a1a1a', }, separator: { height: 1, backgroundColor: '#e0e0e0', }, }); ``` ## State Management with Context and Hooks สำหรับการจัดการ state ระดับง่ายถึงปานกลาง React Context ร่วมกับ hooks เป็นทางเลือกที่มีประสิทธิภาพโดยไม่ต้องพึ่งพาไลบรารีภายนอก ```tsx // context/AuthContext.tsx import React, { createContext, useContext, useState, useCallback } from 'react'; // Types for authentication interface User { id: string; email: string; name: string; } interface AuthContextType { user: User | null; isLoading: boolean; signIn: (email: string, password: string) => Promise; signOut: () => void; } // Creating context with default value const AuthContext = createContext(undefined); // Provider that wraps the application export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(false); // Sign in function const signIn = useCallback(async (email: string, password: string) => { setIsLoading(true); try { // Simulated API call const response = await fetch('https://api.example.com/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }); const data = await response.json(); setUser(data.user); } catch (error) { console.error('Login error:', error); throw error; } finally { setIsLoading(false); } }, []); // Sign out function const signOut = useCallback(() => { setUser(null); }, []); return ( {children} ); } // Custom hook to use the context export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; } ``` ```tsx // screens/LoginScreen.tsx import React, { useState } from 'react'; import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Alert, } from 'react-native'; import { useAuth } from '../context/AuthContext'; export function LoginScreen() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const { signIn, isLoading } = useAuth(); // Form submission handler const handleSubmit = async () => { if (!email || !password) { Alert.alert('Error', 'Please fill in all fields'); return; } try { await signIn(email, password); } catch (error) { Alert.alert('Error', 'Invalid credentials'); } }; return ( Login {isLoading ? ( ) : ( Sign In )} ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', backgroundColor: '#ffffff', }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 32, textAlign: 'center', }, input: { borderWidth: 1, borderColor: '#e0e0e0', borderRadius: 10, padding: 16, marginBottom: 16, fontSize: 16, backgroundColor: '#f9f9f9', }, button: { backgroundColor: '#007AFF', padding: 16, borderRadius: 10, alignItems: 'center', marginTop: 8, }, buttonDisabled: { backgroundColor: '#99c9ff', }, buttonText: { color: '#ffffff', fontSize: 18, fontWeight: '600', }, }); ``` > **State ระดับโกลบอล vs State ระดับโลคอล** > > สำหรับแอปที่ซับซ้อนมากขึ้นที่มี state ใช้ร่วมกันจำนวนมาก โซลูชันอย่าง Zustand หรือ Redux Toolkit อาจเหมาะสมกว่า Context เหมาะสำหรับ state ที่เปลี่ยนแปลงไม่บ่อย (ธีม การยืนยันตัวตน) ## API Calls and Data Management การสื่อสารกับ backend เป็นหัวใจสำคัญของทุกแอปมือถือ ต่อไปนี้เป็นรูปแบบที่แข็งแกร่งโดยใช้ชั้น abstraction สำหรับการเรียก API ```tsx // services/api.ts // Base API configuration const API_BASE_URL = 'https://api.example.com'; // Type for API errors interface ApiError { message: string; code: string; status: number; } // Utility function for requests async function request( endpoint: string, options: RequestInit = {} ): Promise { const url = `${API_BASE_URL}${endpoint}`; const config: RequestInit = { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, }, }; try { const response = await fetch(url, config); if (!response.ok) { const error: ApiError = await response.json(); throw new Error(error.message || 'An error occurred'); } return response.json(); } catch (error) { // Network error handling if (error instanceof TypeError) { throw new Error('Network connection issue'); } throw error; } } // Types for entities interface Product { id: string; name: string; price: number; description: string; imageUrl: string; } // Products service export const productApi = { // Get all products getAll: () => request('/products'), // Get product by ID getById: (id: string) => request(`/products/${id}`), // Create a product create: (data: Omit) => request('/products', { method: 'POST', body: JSON.stringify(data), }), // Update a product update: (id: string, data: Partial) => request(`/products/${id}`, { method: 'PATCH', body: JSON.stringify(data), }), }; ``` ```tsx // hooks/useProducts.ts import { useState, useEffect, useCallback } from 'react'; import { productApi } from '../services/api'; interface Product { id: string; name: string; price: number; description: string; imageUrl: string; } // Custom hook for product management export function useProducts() { const [products, setProducts] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Initial products loading const fetchProducts = useCallback(async () => { setIsLoading(true); setError(null); try { const data = await productApi.getAll(); setProducts(data); } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error'); } finally { setIsLoading(false); } }, []); // Refresh (pull-to-refresh) const refresh = useCallback(async () => { await fetchProducts(); }, [fetchProducts]); // Load on mount useEffect(() => { fetchProducts(); }, [fetchProducts]); return { products, isLoading, error, refresh, }; } ``` ```tsx // screens/ProductListScreen.tsx import React from 'react'; import { View, Text, FlatList, Image, StyleSheet, RefreshControl, ActivityIndicator, } from 'react-native'; import { useProducts } from '../hooks/useProducts'; export function ProductListScreen() { const { products, isLoading, error, refresh } = useProducts(); // Display during initial loading if (isLoading && products.length === 0) { return ( Loading... ); } // Display on error if (error) { return ( {error} ); } return ( item.id} contentContainerStyle={styles.list} // Pull-to-refresh refreshControl={ } renderItem={({ item }) => ( {item.name} ${item.price.toFixed(2)} )} /> ); } const styles = StyleSheet.create({ centered: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, loadingText: { marginTop: 12, fontSize: 16, color: '#666666', }, errorText: { fontSize: 16, color: '#FF3B30', textAlign: 'center', }, list: { padding: 16, }, card: { backgroundColor: '#ffffff', borderRadius: 12, marginBottom: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, image: { width: '100%', height: 200, borderTopLeftRadius: 12, borderTopRightRadius: 12, }, cardContent: { padding: 16, }, productName: { fontSize: 18, fontWeight: '600', color: '#1a1a1a', marginBottom: 4, }, productPrice: { fontSize: 16, color: '#007AFF', fontWeight: '500', }, }); ``` ## Local Data Storage การเก็บข้อมูลในเครื่องช่วยให้ข้อมูลคงอยู่ระหว่างเซสชัน AsyncStorage เป็นโซลูชันมาตรฐานสำหรับข้อมูลอย่างง่าย ขณะที่ SQLite เหมาะกับข้อมูลที่มีโครงสร้างซับซ้อน ```tsx // services/storage.ts import AsyncStorage from '@react-native-async-storage/async-storage'; // Required installation: npx expo install @react-native-async-storage/async-storage // Centralized storage keys const STORAGE_KEYS = { USER_TOKEN: '@app/user_token', USER_PREFERENCES: '@app/user_preferences', ONBOARDING_COMPLETE: '@app/onboarding_complete', } as const; // Types for user preferences interface UserPreferences { theme: 'light' | 'dark' | 'system'; notifications: boolean; language: string; } // Typed storage service export const storage = { // Authentication token async getToken(): Promise { return AsyncStorage.getItem(STORAGE_KEYS.USER_TOKEN); }, async setToken(token: string): Promise { await AsyncStorage.setItem(STORAGE_KEYS.USER_TOKEN, token); }, async removeToken(): Promise { await AsyncStorage.removeItem(STORAGE_KEYS.USER_TOKEN); }, // User preferences (JSON object) async getPreferences(): Promise { const data = await AsyncStorage.getItem(STORAGE_KEYS.USER_PREFERENCES); return data ? JSON.parse(data) : null; }, async setPreferences(prefs: UserPreferences): Promise { await AsyncStorage.setItem( STORAGE_KEYS.USER_PREFERENCES, JSON.stringify(prefs) ); }, // Onboarding async isOnboardingComplete(): Promise { const value = await AsyncStorage.getItem(STORAGE_KEYS.ONBOARDING_COMPLETE); return value === 'true'; }, async setOnboardingComplete(): Promise { await AsyncStorage.setItem(STORAGE_KEYS.ONBOARDING_COMPLETE, 'true'); }, // Complete cleanup async clearAll(): Promise { const keys = Object.values(STORAGE_KEYS); await AsyncStorage.multiRemove(keys); }, }; ``` > **ความปลอดภัยของข้อมูลที่อ่อนไหว** > > สำหรับข้อมูลที่อ่อนไหวเช่น token ยืนยันตัวตน ให้ใช้ expo-secure-store ซึ่งเข้ารหัสข้อมูลผ่าน iOS Keychain และ Android Keystore ## Responsive Styles and Theming แอประดับมืออาชีพต้องรองรับขนาดหน้าจอที่หลากหลายและรองรับโหมดมืด ```tsx // theme/index.ts import { Dimensions, PixelRatio, Platform } from 'react-native'; const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window'); // Reference dimensions (iPhone 14) const guidelineBaseWidth = 390; const guidelineBaseHeight = 844; // Scaling functions export const scale = (size: number) => (SCREEN_WIDTH / guidelineBaseWidth) * size; export const verticalScale = (size: number) => (SCREEN_HEIGHT / guidelineBaseHeight) * size; export const moderateScale = (size: number, factor = 0.5) => size + (scale(size) - size) * factor; // Light theme export const lightTheme = { colors: { primary: '#007AFF', secondary: '#5856D6', success: '#34C759', warning: '#FF9500', error: '#FF3B30', background: '#FFFFFF', surface: '#F2F2F7', text: '#000000', textSecondary: '#8E8E93', border: '#E5E5EA', }, spacing: { xs: scale(4), sm: scale(8), md: scale(16), lg: scale(24), xl: scale(32), }, typography: { h1: { fontSize: moderateScale(32), fontWeight: 'bold' as const, lineHeight: moderateScale(40), }, h2: { fontSize: moderateScale(24), fontWeight: 'bold' as const, lineHeight: moderateScale(32), }, body: { fontSize: moderateScale(16), lineHeight: moderateScale(24), }, caption: { fontSize: moderateScale(14), lineHeight: moderateScale(20), }, }, borderRadius: { sm: scale(4), md: scale(8), lg: scale(12), full: 9999, }, }; // Dark theme export const darkTheme = { ...lightTheme, colors: { ...lightTheme.colors, background: '#000000', surface: '#1C1C1E', text: '#FFFFFF', textSecondary: '#8E8E93', border: '#38383A', }, }; export type Theme = typeof lightTheme; ``` ```tsx // context/ThemeContext.tsx import React, { createContext, useContext, useState, useEffect } from 'react'; import { useColorScheme } from 'react-native'; import { lightTheme, darkTheme, Theme } from '../theme'; import { storage } from '../services/storage'; interface ThemeContextType { theme: Theme; isDark: boolean; toggleTheme: () => void; setThemeMode: (mode: 'light' | 'dark' | 'system') => void; } const ThemeContext = createContext(undefined); export function ThemeProvider({ children }: { children: React.ReactNode }) { const systemColorScheme = useColorScheme(); const [themeMode, setThemeMode] = useState<'light' | 'dark' | 'system'>('system'); // Determine effective theme const isDark = themeMode === 'system' ? systemColorScheme === 'dark' : themeMode === 'dark'; const theme = isDark ? darkTheme : lightTheme; // Load preferences on startup useEffect(() => { storage.getPreferences().then((prefs) => { if (prefs?.theme) { setThemeMode(prefs.theme); } }); }, []); // Toggle between light and dark const toggleTheme = () => { const newMode = isDark ? 'light' : 'dark'; setThemeMode(newMode); storage.getPreferences().then((prefs) => { storage.setPreferences({ ...prefs, theme: newMode, notifications: prefs?.notifications ?? true, language: prefs?.language ?? 'en', }); }); }; return ( {children} ); } export function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; } ``` ## Preparing for Publication ก่อนเผยแพร่แอป มีขั้นตอนการตั้งค่าและการปรับแต่งหลายอย่างที่ต้องดำเนินการ ```json // app.json { "expo": { "name": "MyApp", "slug": "my-app", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "automatic", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#007AFF" }, "ios": { "supportsTablet": true, "bundleIdentifier": "com.example.myapp", "buildNumber": "1" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#007AFF" }, "package": "com.example.myapp", "versionCode": 1 }, "plugins": [ "expo-router" ] } } ``` ```bash # build.sh # EAS Build configuration (Expo Application Services) npm install -g eas-cli # Log in to Expo account eas login # Configure the project eas build:configure # Build for iOS (simulator) eas build --platform ios --profile development # Build for Android (test APK) eas build --platform android --profile preview # Production build eas build --platform all --profile production # Store submission eas submit --platform ios eas submit --platform android ``` > **ใบรับรองและคีย์** > > การเผยแพร่บน iOS ต้องมีบัญชี Apple Developer ($99/ปี) และบน Android ต้องมีบัญชี Google Play Console ($25 จ่ายครั้งเดียว) EAS จัดการใบรับรองสำหรับการเซ็นชื่อโดยอัตโนมัติ ## Conclusion React Native มอบแนวทางที่มีประสิทธิภาพสำหรับการพัฒนาแอปมือถือข้ามแพลตฟอร์ม พื้นฐานที่กล่าวถึงในคู่มือนี้ช่วยให้ท่านสามารถสร้างแอปที่สมบูรณ์และเป็นมืออาชีพได้ ### รายการตรวจสอบสำหรับแอป React Native ที่ประสบความสำเร็จ - ตั้งค่าสภาพแวดล้อมด้วย Expo เพื่อเริ่มต้นอย่างรวดเร็ว - เชี่ยวชาญ component หลัก: View, Text, TouchableOpacity, FlatList - ติดตั้งการนำทางด้วย React Navigation และ TypeScript typing - จัดการ state ด้วย Context API และ custom hooks - จัดโครงสร้างการเรียก API ด้วยชั้น services เฉพาะ - เก็บข้อมูลในเครื่องด้วย AsyncStorage - สร้างระบบธีมแบบ responsive พร้อมรองรับโหมดมืด เอกสารอ้างอิงของ React Native และ Expo ยังคงเป็นแหล่งอ้างอิงหลักสำหรับการศึกษาเจาะลึกแต่ละหัวข้อ ระบบนิเวศพัฒนาอย่างรวดเร็ว และไลบรารีอย่าง React Query หรือ Zustand สามารถช่วยลดความซับซ้อนในการจัดการข้อมูลสำหรับแอปที่ซับซ้อนยิ่งขึ้นได้อีกด้วย --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/react-native/react-native-building-complete-mobile-app