Ders İçeriği

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.

// 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ı

MetodAçıklamaKullanım AlanıBody Gerekli mi?
GETVeri almaKullanıcı listesi, profil bilgisiHayır
POSTYeni veri oluşturmaKullanıcı kaydı, yorum eklemeEvet
PUTVeri güncelleme (tam)Profil güncellemeEvet
PATCHVeri güncelleme (kısmi)Sadece isim güncellemeEvet
DELETEVeri silmeHesap silme, gönderi silmeHayır

Pratik Örnek: Kullanıcı Yönetimi Uygulaması

JSONPlaceholder API'sini kullanarak kullanıcı yönetimi yapan bir uygulama oluşturalım:

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

  

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.

// 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:

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ı

KodAçıklamaAnlamıÖrnek
200OKİstek başarılıVeri başarıyla alındı
201CreatedKaynak oluşturulduYeni kullanıcı eklendi
400Bad RequestGeçersiz istekEksik veya hatalı veri
401UnauthorizedKimlik doğrulama gerekliGiriş yapılmamış
404Not FoundKaynak bulunamadıKullanıcı mevcut değil
500Internal Server ErrorSunucu 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ı