React Native Expo
Standar pengembangan aplikasi menggunakan Expo — managed workflow yang mempercepat development dan deployment React Native.
Expo vs RN CLI
| Kriteria | Expo | RN CLI |
|---|---|---|
| Setup time | ✅ < 5 menit | ⚠️ 30+ menit |
| OTA Updates | ✅ EAS Update | ❌ Manual |
| Build service | ✅ EAS Build (cloud) | ❌ Local only |
| Native modules | ⚠️ Expo Modules API | ✅ Penuh |
| App size | ⚠️ Sedikit lebih besar | ✅ Lebih lean |
| Ejecting | ✅ npx expo prebuild | — |
Gunakan Expo jika:
- Project tidak membutuhkan custom native modules yang kompleks.
- Ingin proses development dan deployment yang lebih cepat.
- Tim tidak memiliki developer yang familiar dengan native Android/iOS development.
- Membutuhkan OTA (Over-the-Air) updates.
Tech Stack
| Kategori | Library | Versi Min. |
|---|---|---|
| Runtime | Expo SDK | 57+ (React Native 0.87, Node.js 22.13+) |
| Language | TypeScript | 5.x |
| Router | Expo Router (file-based) | 57.x (mengikuti versi Expo SDK) |
| State Management | Zustand / Redux Toolkit | Latest |
| Networking | Axios / TanStack Query | Latest |
| Forms | React Hook Form + Zod | Latest |
| UI Library | Tamagui / NativeWind / Gluestack | Latest |
| Local Storage | expo-secure-store / MMKV | Latest |
| Auth | expo-auth-session | Latest |
| Testing | Jest, React Native Testing Library | Latest |
| Linting | ESLint + Prettier | Latest |
| CI/CD | EAS Build + EAS Submit | — |
Expo SDK sudah menjalankan New Architecture (Fabric + TurboModules) secara default sejak SDK 50-an, dan RN CLI sudah menghapus total legacy Bridge sejak 0.82. Kalau ada custom native module dari luar Expo Modules API, pastikan library-nya sudah kompatibel dengan TurboModules sebelum dipasang.
Project Structure (Expo Router)
app/ # File-based routing (Expo Router)
├── _layout.tsx # Root layout
├── index.tsx # Home screen (/)
├── (tabs)/ # Tab navigator group
│ ├── _layout.tsx # Tab layout
│ ├── home.tsx # /home tab
│ ├── search.tsx # /search tab
│ └── profile.tsx # /profile tab
├── (auth)/ # Auth group
│ ├── _layout.tsx
│ ├── login.tsx
│ └── register.tsx
├── user/
│ └── [id].tsx # Dynamic route: /user/:id
└── +not-found.tsx # 404 page
src/
├── core/
│ ├── api/ # Axios instance
│ ├── constants/
│ ├── hooks/
│ ├── theme/
│ └── utils/
├── data/
│ ├── dto/
│ ├── repositories/
│ └── services/
├── domain/
│ ├── entities/
│ ├── repositories/
│ └── usecases/
├── presentation/
│ └── components/ # Shared components
├── store/ # Zustand stores
└── types/
Coding Standards
Expo Router Conventions
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
export default function TabLayout() {
return (
<Tabs screenOptions={{ tabBarActiveTintColor: '#0066FF' }}>
<Tabs.Screen
name="home"
options={{
title: 'Home',
tabBarIcon: ({ color }) => (
<Ionicons name="home" size={24} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color }) => (
<Ionicons name="person" size={24} color={color} />
),
}}
/>
</Tabs>
);
}
EAS Configuration
// eas.json
{
"cli": {
"version": ">= 21.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"channel": "preview"
},
"production": {
"channel": "production"
}
},
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "internal"
},
"ios": {
"appleId": "team@bitgroup.asia",
"ascAppId": "YOUR_APP_STORE_CONNECT_APP_ID"
}
}
}
}
Environment Variables
# .env
EXPO_PUBLIC_API_URL=https://api.staging.bitgroup.asia
EXPO_PUBLIC_ENV=staging
// Variabel berprefix EXPO_PUBLIC_ di-inline otomatis oleh Metro —
// akses langsung via process.env, tanpa app.config extra atau expo-constants.
// HARUS diakses dengan dot notation statis (bukan destructuring/bracket)
// supaya bisa di-inline saat build.
const API_URL = process.env.EXPO_PUBLIC_API_URL;
Variabel EXPO_PUBLIC_* ikut ter-bundle plain-text ke dalam aplikasi dan bisa dibaca siapa saja yang membongkar APK/IPA-nya. Jangan taruh API key rahasia, secret, atau credential di sini — hanya untuk value yang memang aman diketahui client (base URL, feature flag, dsb).
Build & Run
# Create new project
npx create-expo-app@latest my-app --template tabs
# Development
npx expo start
# Build (cloud via EAS)
eas build --platform android --profile preview
eas build --platform ios --profile preview
# Build (local)
npx expo run:android
npx expo run:ios
# OTA Update
eas update --branch preview --message "Fix bug #123"
# Submit to stores
eas submit --platform android --profile production
eas submit --platform ios --profile production
# Tests
npm test
# Lint
npx eslint app/ src/ --fix
Expo mendukung Over-the-Air updates via eas update. Gunakan ini untuk hotfix tanpa harus submit ulang ke App Store / Play Store.
Jika membutuhkan akses ke native code, gunakan npx expo prebuild untuk generate folder android/ dan ios/. Setelah prebuild, project menjadi mirip RN CLI.