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
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/nativeInstall 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:androidEAS Build (recommended)
npm install -g eas-cli eas build -p android
React Native CLI
cd android ./gradlew assembleRelease
Build iOS
# Expo npx expo build:iosEAS 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