React Native Expo Event Management

1

Part 1: Pengenalan & Arsitektur

2

Part 2: Instalasi di Mac, Windows, Ubuntu

3

Part 3: Project Setup

4

Part 4: Autentikasi Admin

5

Part 5: Manajemen Event

6

Part 6: QR Scanner Kehadiran

Artikel ini tersedia dalam Bahasa Inggris

šŸ‡¬šŸ‡§ Read in English

21 Januari 2026

šŸ‡®šŸ‡© Bahasa Indonesia

React Native Expo Event Management Part 7: Polish & Deploy

Finishing touches pada UI, error handling, build APK untuk testing, build AAB untuk Play Store, dan panduan publikasi aplikasi.

7 min read


šŸ“– Overview

Di bagian final ini, kita akan:

  • āœ… Polish UI (loading states, empty states, transitions)
  • āœ… Improve error handling
  • āœ… Build APK untuk internal testing
  • āœ… Build AAB untuk Play Store
  • āœ… Publish ke Google Play Store

✨ Step 1: Polish UI

A. Tambahkan Splash Screen Custom

File: app.json - update splash configuration:

{
  "expo": {
    "splash": {
      "image": "./assets/images/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#1a1a1a"
    }
  }
}

B. Buat Empty State Component

File: components/EmptyState.tsx

import React from 'react';
import { View, Text } from 'react-native';
import { LucideIcon } from 'lucide-react-native';

interface EmptyStateProps {
  icon: LucideIcon;
  title: string;
  description?: string;
}

export function EmptyState({ icon: Icon, title, description }: EmptyStateProps) {
  return (
    <View className="flex-1 items-center justify-center py-20 px-8">
      <Icon size={64} color="#4B5563" />
      <Text className="text-white text-lg font-semibold mt-4 text-center">
        {title}
      </Text>
      {description && (
        <Text className="text-gray-400 text-center mt-2">
          {description}
        </Text>
      )}
    </View>
  );
}

C. Buat Error Boundary Component

File: components/ErrorBoundary.tsx

import React, { Component, ReactNode } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { AlertTriangle } from 'lucide-react-native';

interface Props {
  children: ReactNode;
}

interface State {
  hasError: boolean;
  error?: Error;
}

export class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error };
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: undefined });
  };

  render() {
    if (this.state.hasError) {
      return (
        <View className="flex-1 items-center justify-center bg-secondary px-8">
          <AlertTriangle size={64} color="#ef4444" />
          <Text className="text-white text-xl font-bold mt-4 text-center">
            Oops! Terjadi Kesalahan
          </Text>
          <Text className="text-gray-400 text-center mt-2">
            {this.state.error?.message || 'Something went wrong'}
          </Text>
          <TouchableOpacity
            className="bg-primary px-8 py-4 rounded-xl mt-6"
            onPress={this.handleRetry}
          >
            <Text className="text-white font-bold">Coba Lagi</Text>
          </TouchableOpacity>
        </View>
      );
    }

    return this.props.children;
  }
}

D. Network Status Indicator

File: components/NetworkStatus.tsx

import React, { useEffect, useState } from 'react';
import { View, Text, Animated } from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import { WifiOff } from 'lucide-react-native';

export function NetworkStatus() {
  const [isConnected, setIsConnected] = useState(true);
  const opacity = new Animated.Value(0);

  useEffect(() => {
    const unsubscribe = NetInfo.addEventListener((state) => {
      setIsConnected(state.isConnected ?? true);
    });

    return () => unsubscribe();
  }, []);

  useEffect(() => {
    Animated.timing(opacity, {
      toValue: isConnected ? 0 : 1,
      duration: 300,
      useNativeDriver: true,
    }).start();
  }, [isConnected]);

  if (isConnected) return null;

  return (
    <Animated.View
      style={{ opacity }}
      className="absolute top-0 left-0 right-0 bg-red-600 py-2 px-4 flex-row items-center justify-center z-50"
    >
      <WifiOff size={16} color="#fff" />
      <Text className="text-white ml-2 font-medium">
        Tidak ada koneksi internet
      </Text>
    </Animated.View>
  );
}

Install NetInfo:

npx expo install @react-native-community/netinfo

šŸ”§ Step 2: Improve Error Handling

A. Global Error Handler

File: utils/errorHandler.ts

import { Alert } from 'react-native';

export function handleApiError(error: any, fallbackMessage = 'Terjadi kesalahan') {
  console.error('API Error:', error);

  let message = fallbackMessage;

  if (error.response) {
    // Server responded with error
    message = error.response.data?.error || error.response.data?.message || fallbackMessage;
    
    if (error.response.status === 401) {
      // Token expired - handled by interceptor
      return;
    }
    if (error.response.status === 403) {
      message = 'Anda tidak memiliki akses';
    }
    if (error.response.status === 404) {
      message = 'Data tidak ditemukan';
    }
    if (error.response.status >= 500) {
      message = 'Server sedang bermasalah. Coba lagi nanti.';
    }
  } else if (error.request) {
    // No response received
    message = 'Tidak dapat terhubung ke server. Periksa koneksi internet.';
  }

  Alert.alert('Error', message);
}

B. Retry Logic untuk API Calls

File: utils/retry.ts

export async function withRetry<T>(
  fn: () => Promise<T>,
  retries = 3,
  delay = 1000
): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    if (retries > 0) {
      await new Promise((resolve) => setTimeout(resolve, delay));
      return withRetry(fn, retries - 1, delay * 2);
    }
    throw error;
  }
}

šŸ“¦ Step 3: Build APK untuk Testing

A. Setup EAS Build

# Install EAS CLI
npm install -g eas-cli

# Login ke Expo account
eas login

# Initialize EAS di project
eas build:configure

B. Konfigurasi eas.json

File: eas.json

{
  "cli": {
    "version": ">= 5.0.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      }
    },
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      }
    },
    "production": {
      "android": {
        "buildType": "app-bundle"
      }
    }
  },
  "submit": {
    "production": {
      "android": {
        "serviceAccountKeyPath": "./play-store-key.json"
      }
    }
  }
}

C. Build APK Preview

# Build APK untuk internal testing
eas build --platform android --profile preview

Setelah selesai, download APK dari link yang diberikan.

šŸŖ Step 4: Build AAB untuk Play Store

A. Persiapan Production

  1. Update app.json untuk production:
{
  "expo": {
    "name": "Lampung Dev",
    "slug": "lampung-dev",
    "version": "1.0.0",
    "android": {
      "package": "org.lampungdev.mobile",
      "versionCode": 1,
      "permissions": ["CAMERA"],
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#1a1a1a"
      }
    }
  }
}
  1. Update API URL untuk production di services/api.ts:
export const BASE_URL = __DEV__ 
  ? 'http://192.168.1.100:3000'
  : 'https://lampungdev.org';  // Production URL

B. Build Production AAB

# Build AAB untuk Play Store
eas build --platform android --profile production

Proses ini memakan waktu 10-20 menit. Setelah selesai, download AAB dari link yang diberikan.

šŸš€ Step 5: Publish ke Play Store

A. Persiapan Play Console

  1. Buka Google Play Console
  2. Create new app
  3. Fill app details:
    • App name: Lampung Dev
    • Default language: Indonesian
    • App or game: App
    • Free or paid: Free

B. Store Listing

Siapkan aset berikut:

AssetUkuranFormat
App icon512x512PNG
Feature graphic1024x500PNG
Phone screenshotsMin 2, max 8PNG
Short descriptionMax 80 charsText
Full descriptionMax 4000 charsText

Contoh Short Description:

Aplikasi admin untuk scan kehadiran peserta event LampungDev

Contoh Full Description:

Lampung Dev Mobile adalah aplikasi resmi untuk admin dan panitia komunitas Lampung Dev. Fitur: āœ… Lihat daftar event yang akan datang āœ… Lihat detail event dan peserta terdaftar āœ… Scan QR code untuk verifikasi kehadiran peserta āœ… Catat waktu check-in secara real-time Aplikasi ini hanya untuk admin/panitia event. Untuk mendaftar event, kunjungi lampungdev.org.

C. Upload AAB

  1. Go to Production → Releases
  2. Create new release
  3. Upload AAB file
  4. Add release notes
  5. Review and rollout

D. Content Rating & Privacy

  1. Complete content rating questionnaire
  2. Add privacy policy URL
  3. Complete data safety form

šŸ“Š Step 6: Post-Launch

A. Monitor Crashes

Gunakan EAS Insights atau Firebase Crashlytics:

# Install expo-insights
npx expo install expo-insights

# Enable di app.json
{
  "expo": {
    "plugins": ["expo-insights"]
  }
}

B. App Updates

Untuk update aplikasi:

# Increment version di app.json
"version": "1.0.1",
"android": {
  "versionCode": 2
}

# Build ulang
eas build --platform android --profile production

# Upload ke Play Console

C. OTA Updates (Over-the-Air)

Untuk update tanpa Play Store review:

# Publish OTA update
eas update --branch production --message "Bug fixes"

āœ… Final Checklist

Pre-Launch

  • UI polish (empty states, loading, errors) āœ…
  • Error handling improved āœ…
  • APK tested di device fisik
  • No crashes atau major bugs
  • API production ready

Play Store

  • App icon 512x512
  • Feature graphic 1024x500
  • Screenshots (min 2)
  • Short & full description
  • Privacy policy URL
  • Content rating complete
  • AAB uploaded

Post-Launch

  • Monitor crash reports
  • Respond to user reviews
  • Plan next features

šŸŽ‰ Selamat!

Kamu telah berhasil membangun aplikasi event management lengkap dengan React Native Expo!

Apa yang Sudah Kamu Pelajari:

  1. Arsitektur - System design untuk mobile app
  2. Setup - Environment development di berbagai OS
  3. Project Setup - Expo, NativeWind, folder structure
  4. Authentication - Login, Zustand, SecureStore
  5. Event Management - Lists, cards, detail screens
  6. QR Scanner - Camera, barcode scanning, feedback
  7. Deployment - Build, publish ke Play Store

Source Code

Repository lengkap tersedia di: šŸ”— github.com/Lampung-Dev/lampung-dev-mobile

Kontribusi

Tertarik berkontribusi ke project open source LampungDev? Join komunitas kami:


Semua Parts dalam Series Ini

PartTopik
1Pengenalan & Arsitektur
2Instalasi di Mac, Windows, Ubuntu
3Project Setup
4Autentikasi Admin
5Manajemen Event
6QR Scanner Kehadiran
7Polish & Deploy

Happy Coding! šŸš€

Series ini dibuat untuk mendukung materi Casual Meetup #15 di LampungDev oleh Muhammad Fari Madyan.

Lanjut Membaca

Previous article thumbnail

← Artikel Sebelumnya

React Native Expo Event Management Part 6: QR Scanner Kehadiran