Kembali ke Blog
Cara Membuat Aplikasi Mobile dengan React Native
React Native memungkinkan membuat aplikasi mobile untuk Android dan iOS dengan JavaScript. Mari pelajari dari dasar.
Setup Environment
Prerequisites
# Install Node.js (18+)
# Download dari nodejs.org
# Verify installation
node --version
npm --version
Install React Native CLI
# Install Expo CLI (recommended untuk pemula)
npm install -g expo-cli
# Atau React Native CLI (untuk native modules)
npm install -g react-native-cli
Android Setup
# Install Android Studio
# Download dari developer.android.com
# Set environment variables (Linux/Mac)
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools
# Verify
adb --version
Create New Project
With Expo
# Create project
npx create-expo-app MyApp
cd MyApp
# Start development
npx expo start
# Run on device
# - Scan QR code dengan Expo Go app
# - Atau tekan 'a' untuk Android emulator
# - Atau tekan 'i' untuk iOS simulator
With React Native CLI
# Create project
npx react-native init MyApp
cd MyApp
# Run on Android
npx react-native run-android
# Run on iOS
npx react-native run-ios
Basic Components
View dan Text
import React from "react";
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.title}>Hello React Native!</Text>
<Text style={styles.subtitle}>Ini adalah aplikasi pertama saya</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#f5f5f5",
},
title: {
fontSize: 24,
fontWeight: "bold",
color: "#333",
},
subtitle: {
fontSize: 16,
color: "#666",
marginTop: 10,
},
});
Button dan TouchableOpacity
import { Button, TouchableOpacity, Alert } from "react-native";
function MyComponent() {
const handlePress = () => {
Alert.alert("Halo!", "Button ditekan");
};
return (
<View>
{/* Basic Button */}
<Button title="Tekan Saya" onPress={handlePress} color="#007AFF" />
{/* Custom Button dengan TouchableOpacity */}
<TouchableOpacity
style={styles.customButton}
onPress={handlePress}
activeOpacity={0.7}
>
<Text style={styles.buttonText}>Custom Button</Text>
</TouchableOpacity>
</View>
);
}
Image
import { Image } from "react-native";
function MyComponent() {
return (
<View>
{/* Local image */}
<Image
source={require("./assets/logo.png")}
style={{ width: 100, height: 100 }}
/>
{/* Remote image */}
<Image
source={{ uri: "https://example.com/image.png" }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
/>
</View>
);
}
Input dan Forms
TextInput
import { TextInput } from "react-native";
import { useState } from "react";
function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
return (
<View style={styles.form}>
<TextInput
style={styles.input}
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry={true}
/>
<Button title="Login" onPress={() => console.log(email, password)} />
</View>
);
}
const styles = StyleSheet.create({
form: {
padding: 20,
},
input: {
borderWidth: 1,
borderColor: "#ddd",
padding: 15,
marginBottom: 15,
borderRadius: 8,
fontSize: 16,
},
});
Lists
FlatList
import { FlatList } from "react-native";
function TodoList() {
const todos = [
{ id: "1", title: "Belajar React Native" },
{ id: "2", title: "Buat aplikasi pertama" },
{ id: "3", title: "Deploy ke Play Store" },
];
const renderItem = ({ item }) => (
<View style={styles.todoItem}>
<Text>{item.title}</Text>
</View>
);
return (
<FlatList
data={todos}
renderItem={renderItem}
keyExtractor={(item) => item.id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
}
ScrollView
import { ScrollView } from "react-native";
function LongContent() {
return (
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}>
<Text style={styles.paragraph}>Paragraf 1...</Text>
<Text style={styles.paragraph}>Paragraf 2...</Text>
<Text style={styles.paragraph}>Paragraf 3...</Text>
{/* More content */}
</ScrollView>
);
}
Navigation
Install React Navigation
# Install core
npm install @react-navigation/native
# Install dependencies
npx expo install react-native-screens react-native-safe-area-context
# Install stack navigator
npm install @react-navigation/native-stack
Stack Navigation
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
const Stack = createNativeStackNavigator();
function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate("Details", { itemId: 123 })}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
const { itemId } = route.params;
return (
<View style={styles.container}>
<Text>Details Screen</Text>
<Text>Item ID: {itemId}</Text>
<Button title="Go Back" onPress={() => navigation.goBack()} />
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Tab Navigation
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Ionicons } from "@expo/vector-icons";
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === "Home") {
iconName = focused ? "home" : "home-outline";
} else if (route.name === "Profile") {
iconName = focused ? "person" : "person-outline";
}
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
State Management
useState
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Text style={styles.count}>{count}</Text>
<View style={styles.buttons}>
<Button title="-" onPress={() => setCount(count - 1)} />
<Button title="+" onPress={() => setCount(count + 1)} />
</View>
</View>
);
}
useEffect
import { useState, useEffect } from "react";
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((json) => {
setData(json);
setLoading(false);
})
.catch((error) => {
console.error(error);
setLoading(false);
});
}, []);
if (loading) {
return <ActivityIndicator size="large" />;
}
return (
<View>
<Text>{JSON.stringify(data)}</Text>
</View>
);
}
Styling
Flexbox Layout
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row", // 'column' default
justifyContent: "space-between",
alignItems: "center",
padding: 20,
},
box: {
width: 100,
height: 100,
backgroundColor: "#007AFF",
},
});
Responsive Design
import { Dimensions, useWindowDimensions } from "react-native";
function ResponsiveComponent() {
const { width, height } = useWindowDimensions();
const isLandscape = width > height;
return (
<View
style={[
styles.container,
{ flexDirection: isLandscape ? "row" : "column" },
]}
>
<Text>Width: {width}</Text>
<Text>Height: {height}</Text>
</View>
);
}
API Integration
Fetch Data
const fetchUsers = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching users:", error);
throw error;
}
};
// POST request
const createUser = async (userData) => {
try {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userData),
});
return await response.json();
} catch (error) {
console.error("Error creating user:", error);
throw error;
}
};
Build dan Deploy
Build APK (Android)
# Expo
npx expo build:android
# EAS Build (recommended)
npm install -g eas-cli
eas build -p android
# React Native CLI
cd android
./gradlew assembleRelease
Build iOS
# Expo
npx expo build:ios
# EAS Build
eas build -p ios
# Note: iOS requires Apple Developer account ($99/year)
Kesimpulan
React Native adalah cara efisien untuk membuat aplikasi mobile cross-platform. Mulai dengan Expo untuk development lebih mudah, lalu migrate ke bare workflow jika butuh native modules.
Ditulis oleh
Hendra Wijaya
Artikel Sebelumnya
Cara Membuat Aplikasi PWA (Progressive Web App)
Artikel Selanjutnya
Cara Membuat Bash Script untuk Automation