Tüm Yazılara Dön
Frontend Mimarisi 2024 5 dk okuma Önder Şahin

ReactJs Özel API Servisi ve Interceptor ile API İsteklerini Takip Etme

#ReactJS#Axios#Interceptors#TypeScript#Frontend

Giriş ve Problem Tanımı

Büyük ölçekli React ve Next.js projelerinde API isteklerini yönetmek kritik bir mimari karardır. Her bileşende ayrı ayrı `axios.get()` veya `fetch()` çağrısı yapmak, header yönetimini tekrarlamak ve hata yakalamayı bileşen seviyesinde çözmeye çalışmak kod karmaşasına (spaghetti code) ve bakım maliyetlerinin artmasına yol açar.

Bu rehberde, merkezi bir **Axios Interceptor** ve **Custom Service** katmanı kurarak API iletişimini nasıl standartlaştıracağımızı inceliyoruz.


1. Merkezi HTTP İstemcisi ve Interceptor Mimarisi

İlk adımda tüm HTTP isteklerinin ve yanıtlarının geçeceği bir Axios instance oluşturup `interceptors.request` ve `interceptors.response` fonksiyonlarını tanımlıyoruz:

typescriptCode Snippet
// src/api/http.ts
import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';

const http: AxiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_URL || '/api', timeout: 15000, headers: { 'Content-Type': 'application/json', }, });

// Request Interceptor: Her isteğe dinamik Bearer token ekler http.interceptors.request.use( (config: InternalAxiosRequestConfig) => { if (typeof window !== 'undefined') { const token = localStorage.getItem('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } } return config; }, (error) => Promise.reject(error) );

// Response Interceptor: 401 ve global hataları yakalar http.interceptors.response.use( (response) => response.data, (error) => { if (error.response?.status === 401) { if (typeof window !== 'undefined') { localStorage.removeItem('access_token'); window.location.href = '/login'; } } return Promise.reject(error); } );

export default http; ```


2. Modüler Servis Katmanının Oluşturulması

İstekleri iş mantığına göre modüllere ayırmak, API değişikliklerinde yalnızca ilgili servis dosyasını güncellemeyi sağlar:

typescriptCode Snippet
// src/services/userService.ts
import http from '@/api/http';
import { User, LoginPayload, AuthResponse } from '@/types/user';

export const userService = { login: (payload: LoginPayload): Promise<AuthResponse> => { return http.post('/user/login', payload); }, getProfile: (): Promise<User> => { return http.get('/user/me'); }, updateProfile: (data: Partial<User>): Promise<User> => { return http.patch('/user/me', data); }, }; ```


3. Bileşenlerde Temiz Kullanım

Artık React bileşenleri doğrudan HTTP konfigürasyonunu bilmek zorunda kalmaz:

tsxCode Snippet
import { useState, useEffect } from 'react';
import { userService } from '@/services/userService';
import { User } from '@/types/user';

export default function UserProfile() { const [user, setUser] = useState<User | null>(null);

useEffect(() => { userService.getProfile() .then((data) => setUser(data)) .catch((err) => console.error('Profil yüklenemedi:', err)); }, []);

if (!user) return <div>Yükleniyor...</div>;

return <div>Hoş geldiniz, {user.name}!</div>; } ```

Sonuç ve Kazanımlar - **Tek Noktadan Yetkilendirme**: Token ekleme ve token geçersiz olduğunda yönlendirme tek bir yerde yönetilir. - **Yüksek Test Edilebilirlik**: Servis fonksiyonları kolayca mocklanabilir ve birim testlere dahil edilebilir. - **Tip Güvenliği**: TypeScript arayüzleri ile istek ve yanıt gövdeleri compile-time'da doğrulanır.