API Entegrasyonu Nedir? API (Application Programming Interface) entegrasyonu, React Native uygulamanızın backend servislerle iletişim kurmasını sağlar. Bu sayede veri alışverişi yapabilir, kullanıcı kimlik doğrulaması gerçekleştirebilir ve dinamik içerik sunabilirsiniz.
API Entegrasyonunun Faydaları: Gerçek zamanlı veri güncellemeleri Kullanıcı kimlik doğrulaması ve yetkilendirme Veri senkronizasyonu Üçüncü parti servis entegrasyonları Ölçeklenebilir uygulama mimarisi Fetch API ile HTTP İstekleri React Native'de HTTP istekleri yapmak için yerleşik Fetch API'sini kullanabilirsiniz. Bu API, modern ve promise tabanlı bir yaklaşım sunar.
Kopyala // Temel GET isteği const fetchData = async () => { try { const response = await fetch('https://jsonplaceholder.typicode.com/users'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('Veri alındı:', data); return data; } catch (error) { console.error('Hata:', error); throw error; } }; // POST isteği ile veri gönderme const createUser = async (userData) => { try { const response = await fetch('https://jsonplaceholder.typicode.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); console.log('Kullanıcı oluşturuldu:', result); return result; } catch (error) { console.error('Kullanıcı oluşturma hatası:', error); throw error; } }; // PUT isteği ile veri güncelleme const updateUser = async (userId, userData) => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData), }); const result = await response.json(); return result; } catch (error) { console.error('Güncelleme hatası:', error); throw error; } }; // DELETE isteği const deleteUser = async (userId) => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, { method: 'DELETE', }); if (response.ok) { console.log('Kullanıcı silindi'); return true; } } catch (error) { console.error('Silme hatası:', error); throw error; } };
🌐 HTTP Metodları Metod Açıklama Kullanım Alanı Body Gerekli mi? GET Veri alma Kullanıcı listesi, profil bilgisi Hayır POST Yeni veri oluşturma Kullanıcı kaydı, yorum ekleme Evet PUT Veri güncelleme (tam) Profil güncelleme Evet PATCH Veri güncelleme (kısmi) Sadece isim güncelleme Evet DELETE Veri silme Hesap silme, gönderi silme Hayır
Pratik Örnek: Kullanıcı Yönetimi Uygulaması JSONPlaceholder API'sini kullanarak kullanıcı yönetimi yapan bir uygulama oluşturalım:
Kopyala import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, TextInput, Button, Alert, ActivityIndicator, StyleSheet, TouchableOpacity, } from 'react-native'; const UserManagementApp = () => { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(false); const [newUserName, setNewUserName] = useState(''); const [newUserEmail, setNewUserEmail] = useState(''); // Kullanıcıları yükle const loadUsers = async () => { setLoading(true); try { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await response.json(); setUsers(data); } catch (error) { Alert.alert('Hata', 'Kullanıcılar yüklenirken hata oluştu'); } finally { setLoading(false); } }; // Yeni kullanıcı ekle const addUser = async () => { if (!newUserName.trim() || !newUserEmail.trim()) { Alert.alert('Hata', 'Lütfen tüm alanları doldurun'); return; } setLoading(true); try { const response = await fetch('https://jsonplaceholder.typicode.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: newUserName, email: newUserEmail, }), }); const newUser = await response.json(); // Yerel state'i güncelle setUsers(prevUsers => [...prevUsers, { ...newUser, id: Date.now() }]); setNewUserName(''); setNewUserEmail(''); Alert.alert('Başarılı', 'Kullanıcı eklendi'); } catch (error) { Alert.alert('Hata', 'Kullanıcı eklenirken hata oluştu'); } finally { setLoading(false); } }; // Kullanıcı sil const deleteUser = async (userId) => { Alert.alert( 'Kullanıcı Sil', 'Bu kullanıcıyı silmek istediğinizden emin misiniz?', [ { text: 'İptal', style: 'cancel' }, { text: 'Sil', style: 'destructive', onPress: async () => { setLoading(true); try { await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, { method: 'DELETE', }); // Yerel state'ten kaldır setUsers(prevUsers => prevUsers.filter(user => user.id !== userId)); Alert.alert('Başarılı', 'Kullanıcı silindi'); } catch (error) { Alert.alert('Hata', 'Kullanıcı silinirken hata oluştu'); } finally { setLoading(false); } }, }, ] ); }; // Kullanıcı güncelle const updateUser = async (userId, updatedData) => { setLoading(true); try { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(updatedData), }); const updatedUser = await response.json(); // Yerel state'i güncelle setUsers(prevUsers => prevUsers.map(user => user.id === userId ? { ...user, ...updatedUser } : user ) ); Alert.alert('Başarılı', 'Kullanıcı güncellendi'); } catch (error) { Alert.alert('Hata', 'Kullanıcı güncellenirken hata oluştu'); } finally { setLoading(false); } }; // Bileşen yüklendiğinde kullanıcıları getir useEffect(() => { loadUsers(); }, []); // Kullanıcı kartı render fonksiyonu const renderUser = ({ item }) => ( <View style={styles.userCard}> <View style={styles.userInfo}> <Text style={styles.userName}>{item.name}</Text> <Text style={styles.userEmail}>{item.email}</Text> <Text style={styles.userPhone}>{item.phone}</Text> </View> <View style={styles.userActions}> <TouchableOpacity style={[styles.actionButton, styles.editButton]} onPress={() => { // Güncelleme modalı açılabilir Alert.prompt( 'İsim Güncelle', 'Yeni ismi girin:', (newName) => { if (newName) { updateUser(item.id, { ...item, name: newName }); } } ); }} > <Text style={styles.buttonText}>Düzenle</Text> </TouchableOpacity> <TouchableOpacity style={[styles.actionButton, styles.deleteButton]} onPress={() => deleteUser(item.id)} > <Text style={styles.buttonText}>Sil</Text> </TouchableOpacity> </View> </View> ); return ( <View style={styles.container}> <Text style={styles.title}>Kullanıcı Yönetimi</Text> {/* Yeni kullanıcı ekleme formu */} <View style={styles.addUserForm}> <TextInput style={styles.input} placeholder="İsim" value={newUserName} onChangeText={setNewUserName} /> <TextInput style={styles.input} placeholder="E-posta" value={newUserEmail} onChangeText={setNewUserEmail} keyboardType="email-address" /> <Button title="Kullanıcı Ekle" onPress={addUser} disabled={loading} /> </View> {/* Yenile butonu */} <Button title="Yenile" onPress={loadUsers} disabled={loading} /> {/* Loading göstergesi */} {loading && <ActivityIndicator size="large" color="#3498db" style={styles.loader} />} {/* Kullanıcı listesi */} <FlatList data={users} keyExtractor={(item) => item.id.toString()} renderItem={renderUser} style={styles.userList} showsVerticalScrollIndicator={false} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#f8f9fa', }, title: { fontSize: 24, fontWeight: 'bold', textAlign: 'center', marginBottom: 20, color: '#2c3e50', }, addUserForm: { backgroundColor: 'white', padding: 15, borderRadius: 8, marginBottom: 15, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 3.84, elevation: 5, }, input: { borderWidth: 1, borderColor: '#ddd', padding: 10, borderRadius: 5, marginBottom: 10, fontSize: 16, }, loader: { marginVertical: 20, }, userList: { flex: 1, marginTop: 10, }, userCard: { backgroundColor: 'white', padding: 15, borderRadius: 8, marginBottom: 10, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 3.84, elevation: 5, }, userInfo: { flex: 1, }, userName: { fontSize: 18, fontWeight: 'bold', color: '#2c3e50', marginBottom: 5, }, userEmail: { fontSize: 14, color: '#7f8c8d', marginBottom: 3, }, userPhone: { fontSize: 14, color: '#7f8c8d', }, userActions: { flexDirection: 'row', gap: 10, }, actionButton: { paddingHorizontal: 15, paddingVertical: 8, borderRadius: 5, }, editButton: { backgroundColor: '#3498db', }, deleteButton: { backgroundColor: '#e74c3c', }, buttonText: { color: 'white', fontWeight: 'bold', fontSize: 12, }, }); export default UserManagementApp;
API İsteği Simülasyonu GET - Kullanıcıları Getir POST - Kullanıcı Ekle DELETE - Kullanıcı Sil
Axios Kütüphanesi ile Gelişmiş HTTP İstekleri Axios, HTTP istekleri için daha gelişmiş özellikler sunan popüler bir kütüphanedir. Interceptor'lar, otomatik JSON parsing ve daha iyi hata yönetimi sağlar.
Kopyala // Axios kurulumu npm install axios // Axios ile API servisi oluşturma import axios from 'axios'; // Base URL ve default ayarlar const api = axios.create({ baseURL: 'https://jsonplaceholder.typicode.com', timeout: 10000, headers: { 'Content-Type': 'application/json', }, }); // Request interceptor - her istekte çalışır api.interceptors.request.use( (config) => { // Auth token ekleme const token = getAuthToken(); // Kendi token alma fonksiyonunuz if (token) { config.headers.Authorization = `Bearer ${token}`; } console.log('İstek gönderiliyor:', config); return config; }, (error) => { console.error('İstek hatası:', error); return Promise.reject(error); } ); // Response interceptor - her yanıtta çalışır api.interceptors.response.use( (response) => { console.log('Yanıt alındı:', response); return response; }, (error) => { if (error.response?.status === 401) { // Token süresi dolmuş, yeniden giriş yap handleLogout(); } else if (error.response?.status === 500) { // Sunucu hatası Alert.alert('Hata', 'Sunucu hatası oluştu'); } console.error('Yanıt hatası:', error); return Promise.reject(error); } ); // API fonksiyonları export const userAPI = { // Tüm kullanıcıları getir getUsers: async () => { try { const response = await api.get('/users'); return response.data; } catch (error) { throw new Error('Kullanıcılar alınamadı'); } }, // Tek kullanıcı getir getUser: async (id) => { try { const response = await api.get(`/users/${id}`); return response.data; } catch (error) { throw new Error('Kullanıcı bulunamadı'); } }, // Kullanıcı oluştur createUser: async (userData) => { try { const response = await api.post('/users', userData); return response.data; } catch (error) { throw new Error('Kullanıcı oluşturulamadı'); } }, // Kullanıcı güncelle updateUser: async (id, userData) => { try { const response = await api.put(`/users/${id}`, userData); return response.data; } catch (error) { throw new Error('Kullanıcı güncellenemedi'); } }, // Kullanıcı sil deleteUser: async (id) => { try { await api.delete(`/users/${id}`); return true; } catch (error) { throw new Error('Kullanıcı silinemedi'); } }, }; // Kullanım örneği const UserComponent = () => { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(false); const loadUsers = async () => { setLoading(true); try { const userData = await userAPI.getUsers(); setUsers(userData); } catch (error) { Alert.alert('Hata', error.message); } finally { setLoading(false); } }; const handleCreateUser = async (newUser) => { try { const createdUser = await userAPI.createUser(newUser); setUsers(prev => [...prev, createdUser]); Alert.alert('Başarılı', 'Kullanıcı oluşturuldu'); } catch (error) { Alert.alert('Hata', error.message); } }; useEffect(() => { loadUsers(); }, []); // Component render... };
Hata Yönetimi ve Loading States API isteklerinde etkili hata yönetimi ve kullanıcı deneyimi için loading state'leri çok önemlidir:
Kopyala import React, { useState, useEffect } from 'react'; import { View, Text, ActivityIndicator, Alert } from 'react-native'; // Custom hook for API calls const useApiCall = (apiFunction, dependencies = []) => { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const execute = async (...args) => { setLoading(true); setError(null); try { const result = await apiFunction(...args); setData(result); return result; } catch (err) { setError(err.message); throw err; } finally { setLoading(false); } }; useEffect(() => { if (dependencies.length > 0) { execute(); } }, dependencies); return { data, loading, error, execute }; }; // Hata sınırı bileşeni class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error) { return { hasError: true, error }; } componentDidCatch(error, errorInfo) { console.error('Error Boundary yakaladı:', error, errorInfo); } render() { if (this.state.hasError) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Bir hata oluştu</Text> <Button title="Yeniden Dene" onPress={() => this.setState({ hasError: false })} /> </View> ); } return this.props.children; } } // Loading bileşeni const LoadingComponent = ({ loading, children }) => { if (loading) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" color="#3498db" /> <Text style={{ marginTop: 10 }}>Yükleniyor...</Text> </View> ); } return children; }; // Hata bileşeni const ErrorComponent = ({ error, onRetry }) => { if (!error) return null; return ( <View style={{ padding: 20, alignItems: 'center' }}> <Text style={{ color: 'red', marginBottom: 10 }}>{error}</Text> {onRetry && <Button title="Yeniden Dene" onPress={onRetry} />} </View> ); }; // Ana bileşen const DataComponent = () => { const { data: users, loading, error, execute } = useApiCall(userAPI.getUsers, []); return ( <ErrorBoundary> <View style={{ flex: 1 }}> <ErrorComponent error={error} onRetry={execute} /> <LoadingComponent loading={loading}> {users && ( <FlatList data={users} keyExtractor={(item) => item.id.toString()} renderItem={({ item }) => ( <Text>{item.name}</Text> )} /> )} </LoadingComponent> </View> </ErrorBoundary> ); };
📊 HTTP Status Kodları Kod Açıklama Anlamı Örnek 200 OK İstek başarılı Veri başarıyla alındı 201 Created Kaynak oluşturuldu Yeni kullanıcı eklendi 400 Bad Request Geçersiz istek Eksik veya hatalı veri 401 Unauthorized Kimlik doğrulama gerekli Giriş yapılmamış 404 Not Found Kaynak bulunamadı Kullanıcı mevcut değil 500 Internal Server Error Sunucu hatası Veritabanı bağlantı sorunu
Sonraki Adımlar Bu derste API entegrasyonunu öğrendiniz. Bir sonraki derste veri depolama konusunu ele alacak ve AsyncStorage ile yerel veri saklama yöntemlerini öğreneceksiniz.
Bu Derste Öğrendikleriniz: Fetch API ile HTTP istekleri GET, POST, PUT, DELETE metodları Axios kütüphanesi kullanımı Hata yönetimi ve loading states HTTP status kodları API interceptor'ları