Takip et

React’te useEffect Hook’u ile Web API Çağrıları Nasıl Yapılır?

React’te useEffect Hook’u ile Web API Çağrıları Nasıl Yapılır? React, modern web uygulamaları geliştirmek için popüler bir JavaScript küt

React’te useEffect Hook’u ile Web API Çağrıları Nasıl Yapılır?

React, modern web uygulamaları geliştirmek için popüler bir JavaScript kütüphanesidir. Bileşen tabanlı mimarisi sayesinde kullanıcı arayüzlerini küçük, yeniden kullanılabilir parçalara ayırmayı ve yönetmeyi kolaylaştırır. Ancak, çoğu dinamik web uygulamasının harici veri kaynaklarına, yani Web API’lerine bağlanması gerekir. Kullanıcıların göreceği dinamik içerik, genellikle bir sunucudan veya üçüncü taraf bir hizmetten çekilir. Bu veri çekme (data fetching) işlemleri, React bileşenlerinin yaşam döngüsünde belirli anlarda gerçekleşmesi gereken “yan etkiler” (side effects) kategorisine girer.

React’in sınıf tabanlı bileşenlerinde bu tür yan etkiler componentDidMount, componentDidUpdate ve componentWillUnmount gibi yaşam döngüsü metotları kullanılarak yönetilirdi. Ancak React Hooks’un tanıtılmasıyla birlikte, fonksiyonel bileşenlerde de bu yetenekler useEffect hook’u aracılığıyla sunuldu. useEffect, fonksiyonel bileşenlerde veri çekme, abonelikler kurma veya DOM’u doğrudan manipüle etme gibi yan etkileri gerçekleştirmenin standart yoludur.

Bu makalede, React’te useEffect hook’unu kullanarak Web API çağrılarını nasıl yapacağımızı detaylı bir şekilde inceleyeceğiz. Temel API çağrısı yapısından başlayarak, veri durumunu yönetmeye, bağımlılık dizisini doğru kullanmaya, hata yönetimine, temizleme fonksiyonlarına ve hatta daha gelişmiş senaryolara kadar adım adım ilerleyeceğiz. Amacımız, useEffect ile sağlam, verimli ve hata toleranslı API çağrıları yapma konusunda size kapsamlı bir rehber sunmaktır.

useEffect Hook’una Giriş

useEffect hook’u, React fonksiyonel bileşenlerinde “yan etkileri” gerçekleştirmek için kullanılır. Yan etkiler, bir fonksiyonun ana işlevinin dışında kalan ve dış dünya ile etkileşime giren her türlü eylemi ifade eder. Bir React bileşeni bağlamında, bu genellikle şunları içerir:

* Veri Çekme (Data Fetching): Bir API’den veri almak.
* Abonelikler (Subscriptions): WebSocket gibi harici bir veri kaynağına abone olmak.
* DOM Manipülasyonu: Bileşenin dışında kalan DOM elemanlarını doğrudan değiştirmek (örneğin, belge başlığını güncellemek).
* Zamanlayıcılar (Timers): setTimeout veya setInterval kullanmak.

useEffect‘in temel yapısı şu şekildedir:

useEffect(callback, [dependencies]);

* callback (Geri Çağırma Fonksiyonu): Bu, yan etki mantığınızı içeren fonksiyondur. React, bileşen her render edildiğinde (veya bağımlılıklar değiştiğinde) bu fonksiyonu çalıştırır.
* [dependencies] (Bağımlılık Dizisi): Bu isteğe bağlı bir dizidir ve useEffect‘in ne zaman yeniden çalıştırılacağını kontrol eder.
* Boş dizi ([]): useEffect yalnızca bileşen ilk kez monte edildiğinde (mount) çalışır ve bir daha çalışmaz (sınıf bileşenlerindeki componentDidMount gibidir). Bu, genellikle ilk veri çekme işlemleri için idealdir.
* Hiçbir bağımlılık dizisi yok: useEffect bileşen her render edildiğinde çalışır. Bu, genellikle bir sonsuz döngüye yol açabileceği için dikkatli kullanılmalıdır ve çoğu zaman istenmeyen bir durumdur.
* Değerler içeren bir dizi ([propA, stateB]): useEffect sadece dizideki değerlerden herhangi biri bir önceki render’dan farklıysa çalışır. Bu, belirli prop veya state değişikliklerine tepki vermek için kullanılır.

useEffect‘in dönüş değeri olarak bir fonksiyon döndürülebilir. Bu dönüş fonksiyonu, bileşen kaldırıldığında (unmount) veya useEffect bir sonraki çalıştığında (bağımlılıklar değiştiği için) temizleme (cleanup) işlemi yapmak için kullanılır. Örneğin, abonelikleri iptal etmek veya zamanlayıcıları temizlemek için idealdir. Veri çekme senaryolarında, devam eden bir isteği iptal etmek için kullanılabilir.

Temel API Çağrısı Yapısı

Web API’lerinden veri çekmek için JavaScript’in yerleşik fetch API’sini veya üçüncü taraf kütüphaneleri (örneğin, Axios) kullanabiliriz. Bu makalede fetch API’sine odaklanacağız, çünkü herhangi bir ek kurulum gerektirmez ve modern tarayıcılar tarafından geniş çapta desteklenir.

fetch API’si, Promise tabanlıdır ve asenkron işlemler için async/await sözdizimi ile kullanımı çok daha okunabilir hale gelir. Temel bir fetch isteği şu şekilde görünür:

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error(HTTP error! status: ${response.status});
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Veri çekme hatası:", error);
  }
}

fetchData();

Bu yapıyı useEffect hook’u içine entegre ederken, genellikle bileşenimizin durumu (state) ile etkileşime girmesi gerekir. useState hook’u, bileşenin durumunu yönetmek için kullanılır ve API’den gelen verileri, yükleme durumunu ve hata mesajlarını saklamak için vazgeçilmezdir.

Aşağıda, useEffect ve useState kullanarak basit bir veri çekme örneği verilmiştir:

import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!response.ok) {
          throw new Error(HTTP hatası! Durum: ${response.status});
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    }

    fetchData(); // useEffect içinde tanımlanan asenkron fonksiyonu çağır
  }, []); // Boş bağımlılık dizisi: Sadece bileşen ilk yüklendiğinde çalışır.

  if (loading) return 
Yükleniyor...
; if (error) return
Hata: {error.message}
; return (

API'den Gelen Veri:

Başlık: {data.title}

İçerik: {data.body}

); } export default MyComponent;

Bu örnekte:
1. useState kullanarak data, loading ve error durum değişkenlerini tanımladık. loading başlangıçta true olarak ayarlanmıştır çünkü veri çekme işlemi hemen başlayacaktır.
2. useEffect içinde fetchData adında asenkron bir fonksiyon tanımladık. Bu fonksiyon, API’den veri çeker, başarılı olursa setData ile durumu günceller, bir hata olursa setError ile hatayı kaydeder ve her durumda setLoading(false) ile yükleme durumunu sonlandırır.
3. fetchData() çağrısı, useEffect içinde tanımlandıktan hemen sonra yapılır.
4. Bağımlılık dizisi [] olduğu için, bu useEffect sadece bileşen ilk monte edildiğinde bir kez çalışır.

Veri Durumunu Yönetme

API çağrıları yaparken, verinin kendisi kadar, bu verinin yükleme durumu ve olası hataları da kullanıcıya doğru bir şekilde yansıtılmalıdır. useState hook’u, bu farklı durumları yönetmek için temel araçtır. Genellikle üç ana durum değişkeni kullanılır:

1. data: API’den başarılı bir şekilde çekilen veriyi saklar. Başlangıç değeri null veya boş bir dizi/obje olabilir, beklenen veri tipine göre değişir.
2. isLoading (veya loading): Veri çekme işleminin devam edip etmediğini gösteren bir boolean bayrağıdır. true ise yükleme sürüyor demektir, false ise işlem tamamlanmıştır. Kullanıcıya bir yükleme göstergesi (spinner, iskelet ekran) göstermek için kullanılır.
3. error: API çağrısı sırasında meydana gelen herhangi bir hatayı saklar. Başlangıç değeri null olabilir. Bir hata oluştuğunda, bu değişken hata nesnesini veya mesajını içerir ve kullanıcıya hata mesajını göstermek için kullanılır.

Bu durum değişkenlerinin API çağrısı yaşam döngüsündeki akışı şöyledir:

1. Çağrı Başlamadan Önce:
* setLoading(true)
* setError(null) (önceki hataları temizlemek için)
2. Çağrı Başarılı Olduğunda:
* setData(gelenVeri)
* setLoading(false)
3. Çağrı Başarısız Olduğunda:
* setError(hataObjesi)
* setLoading(false)
4. finally Bloğunda: setLoading(false) genellikle try...catch bloğunun finally kısmında çağrılır, böylece hem başarılı hem de başarısız durumlarda yükleme durumu doğru bir şekilde kapanır.

Yukarıdaki örnekte bu akışı zaten görmüştük. Bu durumları kullanarak bileşen içinde koşullu renderlama yapmak, kullanıcı deneyimini önemli ölçüde artırır:

// ... (önceki import ve useState tanımlamaları)

function MyComponentWithStateManagement() {
  const [posts, setPosts] = useState([]); // Bir dizi beklediğimiz için başlangıç değeri boş dizi
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchPosts = async () => {
      setLoading(true); // Yükleme başladı
      setError(null);   // Önceki hataları temizle
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts');
        if (!response.ok) {
          throw new Error(HTTP hatası! Durum: ${response.status});
        }
        const data = await response.json();
        setPosts(data); // Veri başarıyla alındı
      } catch (err) {
        setError(err); // Hata oluştu
      } finally {
        setLoading(false); // Yükleme tamamlandı (başarılı veya başarısız)
      }
    };

    fetchPosts();
  }, []);

  if (loading) {
    return 

Gönderiler yükleniyor...

{/ Buraya bir spinner veya iskelet ekran eklenebilir /}
; } if (error) { return

Veri çekilirken bir hata oluştu: {error.message}

; } return (
{posts.map(post => (

{post.title}

{post.body}

))}
); } export default MyComponentWithStateManagement;

Bu örnek, kullanıcıya akıcı bir deneyim sunmak için yükleme ve hata durumlarının nasıl yönetildiğini daha net gösterir.

Bağımlılık Dizisi ve Kontrollü Yeniden Çalışma

useEffect hook’unun ikinci argümanı olan bağımlılık dizisi, performans ve doğru çalışma açısından kritik öneme sahiptir. Bu dizi, useEffect içindeki yan etkinin ne zaman yeniden çalıştırılacağını belirler.

1. Boş Bağımlılık Dizisi ([])

useEffect‘in sadece bileşen ilk monte edildiğinde çalışmasını sağlar. Bu, sınıf bileşenlerindeki componentDidMount metoduna karşılık gelir. Genellikle bir bileşenin yaşam döngüsünde yalnızca bir kez yapılması gereken veri çekme işlemleri için kullanılır.

useEffect(() => {
  // Bu kod sadece bileşen ilk kez DOM'a eklendiğinde çalışır.
  // Örnek: İlk sayfa yüklendiğinde bir listeyi çekmek.
  fetch('https://api.example.com/initial-data').then(...);
}, []); // Boş dizi

2. Bağımlılık Dizisi Yok

Eğer ikinci argüman olarak bağımlılık dizisi belirtilmezse, useEffect bileşen her render edildiğinde çalışır. Bu, genellikle istenmeyen bir durumdur ve sonsuz döngülere yol açabilir, özellikle useState güncellemeleri içeriyorsa.

useEffect(() => {
  // DİKKAT: Bu kod her render'da çalışır!
  // Eğer bu içinde bir state güncelleniyorsa, sonsuz döngüye girebilirsiniz.
  console.log('Her renderda çalışıyorum!');
}); // Bağımlılık dizisi yok

3. Değerler İçeren Bağımlılık Dizisi ([value1, value2])

useEffect içindeki yan etkinin, dizideki değerlerden herhangi biri bir önceki render’dan farklıysa yeniden çalışmasını sağlar. Bu, belirli prop veya state değişikliklerine tepki vermek için idealdir. Örneğin, bir kullanıcının ID’si değiştiğinde o kullanıcının verilerini çekmek gibi.

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch(https://jsonplaceholder.typicode.com/users/${userId});
        if (!response.ok) {
          throw new Error(Kullanıcı bulunamadı! Durum: ${response.status});
        }
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    if (userId) { // userId'nin geçerli olduğundan emin ol
      fetchUser();
    } else {
      setUser(null);
      setLoading(false);
    }
    
  }, [userId]); // userId değiştiğinde useEffect yeniden çalışır

  if (loading) return 
Kullanıcı bilgileri yükleniyor...
; if (error) return
Hata: {error.message}
; if (!user) return
Lütfen bir kullanıcı seçin.
; return (

Kullanıcı Profili: {user.name}

E-posta: {user.email}

Şehir: {user.address.city}

); } export default UserProfile;

Bu örnekte, userId prop’u useEffect‘in bağımlılık dizisine dahil edilmiştir. Bu sayede, UserProfile bileşenine farklı bir userId prop’u geldiğinde (örneğin bir üst bileşenden), useEffect yeniden çalışacak ve yeni kullanıcı için veri çekecektir.

Önemli Not: Bağımlılık dizisine eklenen her değişken, useEffect‘in doğru çalışması için stabil olmalıdır. Eğer diziye bir obje veya fonksiyon gibi referans tipli bir değişken ekler ve bu değişken her render’da yeniden oluşturulursa (örneğin, doğrudan useEffect içinde bir obje oluşturup bağımlılık olarak vermek), useEffect her zaman bu değişkenin değiştiğini düşünecek ve sonsuz bir döngüye girecektir. Bu tür durumlar için useCallback veya useMemo hook’ları kullanılabilir, ancak çoğu basit API çağrısı senaryosunda bu kadar ileri gitmeye gerek kalmaz.

Hata Yönetimi

API çağrılarında hata yönetimi, uygulamanın sağlamlığı ve kullanıcı deneyimi için kritik öneme sahiptir. Ağ hataları, sunucu hataları (4xx, 5xx), veya API’den gelen geçersiz yanıtlar gibi çeşitli sorunlarla karşılaşılabilir.

fetch API’si, ağ hataları (örneğin, internet bağlantısı yok) durumunda bir Promise’i reddeder, ancak HTTP durum kodları (örneğin, 404 Not Found veya 500 Internal Server Error) durumunda Promise’i reddetmez; bunun yerine response.ok özelliğini false olarak ayarlar. Bu nedenle, hem ağ hatalarını hem de HTTP durum hatalarını ayrı ayrı ele almak önemlidir.

// ... (önceki import ve useState tanımlamaları)

function ErrorHandlingComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/nonexistent-endpoint'); // Bilerek hatalı bir URL
        
        // HTTP durum kodunu kontrol et
        if (!response.ok) {
          // Hata durumunda response.json() ile sunucudan gelen hata mesajını almaya çalışabiliriz
          const errorData = await response.json().catch(() => ({ message: 'Bilinmeyen sunucu hatası.' }));
          throw new Error(HTTP hatası! Durum: ${response.status} - ${errorData.message || response.statusText});
        }
        
        const result = await response.json();
        setData(result);
      } catch (err) {
        // Ağ hataları veya yukarıdaki throw new Error yakalanır
        console.error("Veri çekme sırasında bir hata oluştu:", err);
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) return 
Yükleniyor...
; if (error) return
Hata: {error.message}
; return (

API'den Gelen Veri:

{data ?

{data.title}

:

Veri bulunamadı.

}
); } export default ErrorHandlingComponent;

Bu örnekte:
* try...catch bloğu, hem fetch Promise’inin reddedilmesi durumunda (ağ hatası) hem de bizim manuel olarak throw new Error ile fırlattığımız durumlarda (HTTP durum hatası) hataları yakalar.
* response.ok kontrolü, 200-299 aralığında olmayan HTTP durum kodlarını yakalamak için kullanılır.
* response.json().catch(() => ...) ile, sunucudan gelen hata mesajını (eğer varsa) almaya çalışırız. Eğer JSON parse edilemezse, varsayılan bir hata mesajı kullanılır.
* setError(err) ile hata durumunu güncelleyip kullanıcıya gösteririz.

Temizleme Fonksiyonları

useEffect hook’u, bileşen kaldırıldığında (unmount) veya bağımlılıklar değiştiğinde önceki yan etkinin temizlenmesini sağlayan bir fonksiyon döndürebilir. Bu temizleme fonksiyonu, özellikle abonelikleri iptal etmek, zamanlayıcıları durdurmak veya devam eden ağ isteklerini iptal etmek gibi durumlarda bellek sızıntılarını ve istenmeyen davranışları önlemek için çok önemlidir.

API çağrıları söz konusu olduğunda, bir bileşen kaldırılmadan önce devam eden bir fetch isteğini iptal etmek, “Can’t perform a React state update on an unmounted component” (Kaldırılmış bir bileşende React durum güncellemesi yapılamaz) uyarısını önlemenin yaygın bir yoludur. fetch API’si doğrudan bir iptal mekanizmasına sahip olmasa da, AbortController API’si bu işlevi sağlar.

import React, { useState, useEffect } from 'react';

function AbortableFetchComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const abortController = new AbortController(); // Yeni bir AbortController oluştur
    const signal = abortController.signal; // İptal sinyalini al

    const fetchData = async () => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1', { signal }); // İstekle birlikte sinyali gönder
        
        if (!response.ok) {
          throw new Error(HTTP hatası! Durum: ${response.status});
        }
        
        const result = await response.json();
        setData(result);
      } catch (err) {
        // Eğer hata AbortError ise, isteğin iptal edildiği anlamına gelir.
        // Bu durumda state güncellemesi yapmayız.
        if (err.name === 'AbortError') {
          console.log('Fetch isteği iptal edildi.');
        } else {
          setError(err);
        }
      } finally {
        setLoading(false);
      }
    };

    fetchData();

    // Temizleme fonksiyonu: Bileşen kaldırıldığında veya bağımlılıklar değiştiğinde çalışır.
    return () => {
      abortController.abort(); // Devam eden isteği iptal et
    };
  }, []); // Bağımlılık dizisi boş

  if (loading) return 
Yükleniyor...
; if (error) return
Hata: {error.message}
; return (

API'den Gelen Veri (İptal Edilebilir):

Başlık: {data.title}

İçerik: {data.body}

); } export default AbortableFetchComponent;

Bu örnekte:
1. AbortController nesnesi oluşturulur ve signal özelliği fetch isteğine signal seçeneği olarak geçirilir.
2. useEffect‘ten dönen temizleme fonksiyonunda abortController.abort() çağrılır. Bu, fetch isteğini iptal eder.
3. catch bloğunda, hatanın AbortError olup olmadığını kontrol ederiz. Eğer öyleyse, bu bir iptal hatasıdır ve genellikle kullanıcıya gösterilmesi gereken gerçek bir hata değildir, bu yüzden setError çağrısından kaçınırız.

Bu mekanizma, özellikle kullanıcı bir sayfadan hızlıca ayrıldığında veya bir bileşen dinamik olarak kaldırıldığında, gereksiz ağ trafiğini ve React’in kaldırmış olduğu bir bileşende durum güncellemesi yapmaya çalışmasından kaynaklanan uyarıları önler.

Gelişmiş Kullanım Senaryoları ve İpuçları

useEffect ile API çağrıları yapmak temel düzeyde yeterli olsa da, daha karmaşık uygulamalar ve daha iyi geliştirici deneyimi için bazı gelişmiş teknikler ve kütüphaneler mevcuttur.

1. Custom Hooks (Özel Hook’lar)

API çağrısı mantığını birden fazla bileşende kullanmanız gerektiğinde, bu mantığı özel bir hook içine kapsüllemek çok faydalıdır. Bu, kod tekrarını azaltır, okunabilirliği artırır ve test edilebilirliği kolaylaştırır.

// useFetch.js
import { useState, useEffect } from 'react';

function useFetch(url, options) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const abortController = new AbortController();
    const signal = abortController.signal;

    const fetchData = async () => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch(url, { ...options, signal });
        if (!response.ok) {
          throw new Error(HTTP hatası! Durum: ${response.status});
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        if (err.name === 'AbortError') {
          console.log('Fetch isteği iptal edildi:', url);
        } else {
          setError(err);
        }
      } finally {
        setLoading(false);
      }
    };

    if (url) { // URL varsa isteği yap
      fetchData();
    } else { // URL yoksa, hemen yüklemeyi bitir
      setLoading(false);
    }

    return () => {
      abortController.abort();
    };
  }, [url, JSON.stringify(options)]); // URL veya options değiştiğinde yeniden çalış

  return { data, loading, error };
}

export default useFetch;

Bu useFetch hook’unu bir bileşende kullanmak çok daha temiz olacaktır:

// MyComponentUsingCustomHook.js
import React from 'react';
import useFetch from './useFetch'; // useFetch hook'umuzu import ediyoruz

function MyComponentUsingCustomHook() {
  const { data: post, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts/2');

  if (loading) return 
Yükleniyor...
; if (error) return
Hata: {error.message}
; return (

Custom Hook ile Gelen Veri:

Başlık: {post.title}

İçerik: {post.body}

); } export default MyComponentUsingCustomHook;

2. Axios Kütüphanesi

fetch API’si harika olsa da, Axios gibi üçüncü taraf bir kütüphane, API çağrıları için ek özellikler ve daha rahat bir kullanım sunar:
* Otomatik JSON dönüştürme
* İstek/Yanıt interceptor’ları
* Daha iyi hata yönetimi (HTTP durum kodları için Promise’i otomatik reddetme)
* İsteği iptal etme (yerleşik cancelToken)

Axios ile bir useEffect çağrısı şöyle görünebilir:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function AxiosFetchComponent() {
  const [todos, setTodos] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const source = axios.CancelToken.source(); // Axios iptal token'ı
    
    const fetchTodos = async () => {
      setLoading(true);
      setError(null);
      try {
        const response = await axios.get('https://jsonplaceholder.typicode.com/todos', {
          cancelToken: source.token // İptal token'ını isteğe ekle
        });
        setTodos(response.data);
      } catch (err) {
        if (axios.isCancel(err)) {
          console.log('Axios isteği iptal edildi:', err.message);
        } else {
          setError(err);
        }
      } finally {
        setLoading(false);
      }
    };

    fetchTodos();

    return () => {
      source.cancel('İstek temizleme sırasında iptal edildi.'); // Temizleme fonksiyonunda iptal et
    };
  }, []);

  if (loading) return 
Yapılacaklar yükleniyor...
; if (error) return
Hata: {error.message}
; return (

Yapılacaklar Listesi (Axios ile)

    {todos.slice(0, 5).map(todo => ( // İlk 5 tanesini gösterelim
  • {todo.title} - {todo.completed ? 'Tamamlandı' : 'Bekliyor'}
  • ))}
); } export default AxiosFetchComponent;

3. Veri Önbellekleme ve Durum Yönetimi Kütüphaneleri

Büyük ölçekli uygulamalarda, API çağrılarını sadece bir kez yapmak, veriyi önbelleğe almak, arka planda yeniden doğrulamak, senkronizasyon sağlamak ve global durumu yönetmek gibi ihtiyaçlar ortaya çıkar. Bu durumlar için React Query (TanStack Query) veya SWR gibi kütüphaneler useEffect‘e göre çok daha gelişmiş çözümler sunar. Bu kütüphaneler, useEffect‘in üzerine inşa edilmiş olsa da, veri çekme, önbellekleme, hata yönetimi ve yükleme durumları gibi karmaşık senaryoları otomatikleştirerek geliştiriciye büyük kolaylık sağlarlar.

Örneğin, React Query ile bir veri çekme işlemi sadece birkaç satır kodla yapılabilir ve önbellekleme, yeniden deneme, arka plan güncelleme gibi birçok özellik otomatik olarak gelir.

// React Query örneği (kurulum ve Context Provider gerektirir)
import { useQuery } from '@tanstack/react-query';

function ReactQueryComponent() {
  const { isLoading, error, data } = useQuery({
    queryKey: ['todos'], // Önbellek anahtarı
    queryFn: async () => { // Veri çekme fonksiyonu
      const response = await fetch('https://jsonplaceholder.typicode.com/todos');
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    }
  });

  if (isLoading) return 
Yükleniyor...
; if (error) return
Hata: {error.message}
; return (

Yapılacaklar Listesi (React Query ile)

    {data.slice(0, 5).map(todo => (
  • {todo.title}
  • ))}
); }

Bu kütüphaneler, useEffect‘i doğrudan kullanma ihtiyacını azaltarak, veri katmanını daha soyut ve yönetilebilir hale getirir.

En İyi Uygulamalar ve Sık Yapılan Hatalar

useEffect ile API çağrıları yaparken dikkat edilmesi gereken bazı önemli noktalar ve kaçınılması gereken yaygın hatalar vardır:

1. Yan Etkileri Yalıtma: useEffect sadece yan etkiler için kullanılmalıdır. Bileşenin render çıktısını doğrudan etkilemeyen, ancak dış dünya ile etkileşime giren işlemler için idealdir. Durum güncellemelerini useEffect dışında, olay işleyicilerinde yapmak daha uygundur.
2. Sonsuz Döngüleri Önleme: En yaygın hatalardan biri, bağımlılık dizisini yanlış kullanmak veya hiç kullanmamaktır. useEffect içindeki bir durum güncellemesi, bileşenin yeniden render olmasına neden olabilir ve eğer bağımlılık dizisi doğru ayarlanmamışsa, useEffect tekrar çalışarak tekrar bir durum güncellemesi tetikleyebilir ve bu bir sonsuz döngüye yol açabilir. Bu nedenle, bağımlılık dizisine dikkat edin ve referans tipli değişkenler için useCallback veya useMemo kullanmayı düşünün.
3. Temizleme Fonksiyonlarını Kullanma: Özellikle uzun süreli işlemler (abonelikler, zamanlayıcılar, ağ istekleri) için temizleme fonksiyonları mutlaka kullanılmalıdır. Bu, bellek sızıntılarını ve “unmounted component” uyarılarını önler. AbortController bunun için harika bir araçtır.
4. Hata Yönetimini İhmal Etmeme: API çağrıları her zaman başarısız olabilir. Uygulamanızın bu durumları zarifçe ele alması ve kullanıcıya anlamlı geri bildirimler sunması önemlidir. try...catch blokları ve response.ok kontrolü vazgeçilmezdir.
5. Gereksiz Yeniden Çalışmaları Azaltma: Bağımlılık dizisini doğru ayarlamak, useEffect‘in sadece gerçekten gerektiğinde çalışmasını sağlar. Bu, gereksiz API çağrılarını ve performans sorunlarını önler.
6. Kullanıcı Deneyimi: Yükleme durumlarını (spinner, iskelet ekranı) ve hata mesajlarını açıkça göstermek, kullanıcı deneyimini önemli ölçüde iyileştirir.
7. Custom Hooks ile Soyutlama: Tekrar eden API çağrısı mantıklarını custom hook’lar içine taşımak, kodunuzu daha modüler, yeniden kullanılabilir ve okunabilir hale getirir.

Sonuç

useEffect hook’u, React fonksiyonel bileşenlerinde Web API çağrıları gibi yan etkileri yönetmek için güçlü ve esnek bir araçtır. Bu makalede, useEffect‘in temel prensiplerinden başlayarak, useState ile veri durumunu yönetmeye, bağımlılık dizisinin doğru kullanımına, sağlam hata yönetimine ve bellek sızıntılarını önlemek için temizleme fonksiyonlarına kadar birçok önemli konuyu ele aldık. Ayrıca, useFetch gibi özel hook’lar oluşturarak kod tekrarını nasıl azaltacağımızı, Axios gibi kütüphanelerin sunduğu avantajları ve daha büyük uygulamalar için React Query veya SWR gibi veri çekme kütüphanelerinin önemini inceledik.

useEffect‘i doğru bir şekilde anlamak ve kullanmak, React uygulamalarınızda dinamik verileri etkili bir şekilde çekmenizi, kullanıcıya akıcı bir deneyim sunmanızı ve uygulamanızın performansını ve sürdürülebilirliğini artırmanızı sağlayacaktır. Unutmayın, iyi bir React geliştiricisi olmak, sadece bileşenleri render etmekle kalmaz, aynı zamanda dış dünya ile olan etkileşimleri (yani yan etkileri) ustaca yönetmekle de ilgilidir.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Exit mobile version