React Query (with vs useEffect)

Onur Sert
6 min readDec 13, 2023

--

React Query, React uygulamalarında veri yönetimini kolaylaştırmak için kullanılan bir kütüphanedir. Bu kütüphane, özellikle uzak sunucu tarafından sağlanan verilerle çalışırken, veri alışverişini yönetmeyi ve önbelleğe almayı sağlar. React Query, sunucu verilerini getirme, önbelleğe alma, güncelleme ve silme gibi temel veritabanı işlemlerini kolayca gerçekleştirmenizi sağlayan basit bir yapı sağlar.

Basitçe Kurulum

Kurulum

React Query’yi projenize eklemek için aşağıdaki gibi bir paket yöneticisi kullanabilirsiniz:

npm install react-query
yarn add react-query

Provider Eklenmesi

React Query’i kullanmak için, <QueryClientProvider> bileşenini projenize eklemeniz gerekiyor. Bu, React Query'nin genel durum yönetimini sağlar.

import { QueryClient, QueryClientProvider } from 'react-query';

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Uygulama bileşenleri buraya gelecek */}
</QueryClientProvider>
);
}

Sorgular

Verileri almak için sorguları tanımlamanız gerekir. useQuery hook'u kullanılır:

import React, { useState, useEffect } from 'react';
import { useQuery } from 'react-query';

const fetchDataFunction = async () => {
try {
const response = await fetch('<https://jsonplaceholder.typicode.com/users>');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error.message);
throw error;
}
};

const MyComponent = () => {
const { data, isLoading, error } = useQuery('myData', fetchDataFunction);
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
<h1>User List</h1>
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};

export default MyComponent;

Bu örnekte, useQuery hook'u kullanılarak fetchDataFunction fonksiyonu ile veri çekilmiştir. isLoading durumunu kontrol ederek yüklenme durumunu, error durumunu kontrol ederek hata durumunu ele alıyoruz. Eğer veri başarıyla alındıysa, kullanıcı listesini ekrana yazdırıyoruz.

Mutasyonlar

Verileri güncellemek, eklemek veya silmek için useMutation hook'u kullanılır:

import React from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';

const fetchDataFunction = async () => {
// Fetch işlemi
};

const updateDataFunction = async (updatedUserData) => {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${updatedUserData.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updatedUserData),
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const updatedData = await response.json();
return updatedData;
} catch (error) {
console.error('Error updating data:', error.message);
throw error;
}
};

const MyComponent = () => {
const queryClient = useQueryClient();
const { data, isLoading, error } = useQuery('myData', fetchDataFunction);
const mutation = useMutation(updateDataFunction, {
onSuccess: (updatedData) => {
// Veri güncelleme başarılı olduğunda yapılacak işlemler
// Örneğin, güncellenmiş veriyi tekrar önbelleğe alabiliriz
queryClient.setQueryData('myData', (prevData) => {
return prevData.map((user) => (user.id === updatedData.id ? updatedData : user));
});
},
});
const handleUpdate = (userId, newUserName) => {
const updatedUserData = {
id: userId,
name: newUserName
};
mutation.mutate(updatedUserData);
};
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
<h1>User List</h1>
<ul>
{data.map((user) => (
<li key={user.id}>
{user.name}{' '}
<button onClick={() => handleUpdate(user.id, `New ${user.name}`)}>
Update Name
</button>
</li>
))}
</ul>
</div>
);
};

export default MyComponent;

Bu örnekte, useMutation hook'u kullanarak bir güncelleme işlemi gerçekleştiriyoruz. updateDataFunction fonksiyonu, belirli bir kullanıcının adını güncellemek için kullanılıyor. onSuccess opsiyonu, güncelleme işlemi başarıyla tamamlandığında yapılacak işlemleri sağlar. Örneğin, güncellenmiş veriyi tekrar önbelleğe alabilir veya başka bir şey yapabilirsiniz.

Örnek

Aşağıda basit bir React uygulaması içinde React Query kullanımına dair örnek bir komponent bulabilirsiniz. Bu örnekte, kullanıcılar adlı bir veri kaynağını çekme işlemini simüle eden bir örnek bulunmaktadır.

// App.js
import React from 'react';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';

const queryClient = new QueryClient();

const fetchUsers = async () => {
// Simülasyon amaçlı, gerçek bir API çağrısı yapabilirsiniz.
const response = await fetch('<https://jsonplaceholder.typicode.com/users>');
const data = await response.json();
return data;
};

const UserList = () => {
const { data: users, isLoading, error } = useQuery('users', fetchUsers);
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
<h1>User List</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};

const App = () => {
return (
<QueryClientProvider client={queryClient}>
<UserList />
</QueryClientProvider>
);
};

export default App;

useEffect ve React Query Kullanarak Veri Çekme Farkları

useEffect ve React Query ile veri çekme arasında birkaç önemli fark bulunmaktadır. İşte bu iki yöntemin kullanımı ve farklılıkları:

Optimizasyon ve Önbellekleme:

  • useEffect: useEffect kullanarak veri çektiğinizde, veri çekme işlemi genellikle her render'da gerçekleşir ve her güncellemede aynı işlemi tekrarlamak zorunda kalırsınız. Bu, performans sorunlarına yol açabilir ve aynı veriyi birden çok kez çekmek anlamına gelebilir.
  • React Query: React Query, veriyi önbellekleme yeteneği sağlar. İlk çağrıda alınan veriyi önbellekte saklar ve bu sayede aynı veriye tekrar tekrar ihtiyaç duyulduğunda tekrar sorgulama yapmadan önbellekten alabilir. Bu, uygulamanın performansını artırabilir ve gereksiz ağ trafiğini azaltabilir.

Hata Yönetimi:

  • useEffect: useEffect içinde gerçekleştirilen asenkron işlemlerde hata yönetimi genellikle try-catch blokları kullanılarak yapılır. Hataların nasıl ele alınacağı ve kullanıcıya nasıl gösterileceği konusunda daha fazla manuel müdahale gerekebilir.
  • React Query: React Query, hata yönetimi için özel olarak tasarlanmıştır. useQuery veya useMutation hook'ları kullanıldığında, hatalar otomatik olarak işlenir ve hata durumunda bileşen yeniden render edilir. Bu, daha tutarlı ve kullanıcı dostu bir hata yönetimi sağlar.

İlk Render Davranışı:

  • useEffect: useEffect içindeki veri çekme işlemleri, genellikle component ilk render edildiğinde tetiklenir. Bu, bazen sayfa yüklendiğinde gerekli olmayan veri çağrılarını içerebilir.
  • React Query: React Query, varsayılan olarak veriyi ilk kez lazım olduğunda çeker. Yani, bileşen render edildiğinde değil, gerçekten veriye ihtiyaç olduğunda asenkron bir şekilde veriyi almaya başlar. Bu, sayfa yüklendiğinde gereksiz veri alımını önleyebilir.

Optimizasyon ve Yönetim:

  • useEffect: useEffect daha genel bir kullanıma sahiptir ve manuel optimizasyonlar ve yönetim gerektirebilir.
  • React Query: React Query, veri yönetimi konusunda özel olarak tasarlanmıştır ve önbellekleme, otomatik yeniden sorgulama gibi optimizasyonları sağlar. Veri alışverişi, güncelleme ve hata yönetimi gibi işlemleri kolayca gerçekleştirmenizi sağlar.

Sonuç olarak, React Query, veri yönetimini daha etkili ve optimizasyon odaklı bir şekilde ele alırken, useEffect genelde daha geniş bir kullanım alanına sahiptir ve daha fazla manuel kontrol gerektirebilir. Ancak, kullanılacak yöntem uygulamanın ihtiyaçlarına ve karmaşıklığına bağlı olarak değişebilir.

Önbellekleme

React Query, önbellekleme işlemlerini otomatik olarak yöneten bir kütüphanedir. Önbellekleme, aynı veriye tekrar tekrar sorgu yapmadan önce sonuçları bir süre saklamak anlamına gelir. Bu, uygulamanın performansını artırabilir ve ağ trafiğini azaltabilir. Varsayılan olarak, her bir sorgu için sonuçlar 5 dakika süreyle önbellekte tutulur.

React Query’de birkaç önbellekleme stratejisi bulunmaktadır ve bu stratejileri cacheTime özelliğini kullanarak özelleştirebilirsiniz. Örnek olarak:

import { useQuery } from 'react-query';

const fetchData = async () => {
// API'den veri çekme işlemi
};

const MyComponent = () => {
const { data, isLoading, error } = useQuery('myData', fetchData, {
cacheTime: 60000, // 1 dakika (milisaniye cinsinden)
});
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
{/* Veri kullanma */}
</div>
);
};

Bu örnekte, useQuery hook'u ile bir sorgu gerçekleştirilirken cacheTime özelliği kullanılarak önbellek süresi 1 dakika olarak belirlenmiştir. Bu, aynı sorgunun bir dakika içinde tekrarlanması durumunda, önbellekteki sonuçların kullanılmasını sağlar.

React Query’nin varsayılan olarak sağladığı önbellekleme stratejisi genellikle uygundur, ancak ihtiyacınıza göre bu stratejiyi özelleştirebilirsiniz. Ayrıca, staleTime ve refetchInterval gibi diğer seçeneklerle de önbellek davranışını daha ayrıntılı bir şekilde kontrol edebilirsiniz. Bu seçeneklerle ilgili daha fazla bilgiye React Query belgelerinde ulaşabilirsiniz.

staleTime ve cacheTime özellikleri, React Query'de kullanılan önbellekleme stratejilerini belirlemek için kullanılır, ancak farklı amaçlara hizmet ederler.

staleTime:

  • staleTime, bir sorgunun önbellekteki verilerinin ne kadar süre boyunca güncel kabul edileceğini belirler.
  • Eğer staleTime süresi içinde aynı sorgu tekrarlanırsa, önbellekten alınan veriler hemen kullanılır ve aynı zamanda arka planda gerçek bir sorgu başlatılır.
  • Örneğin, staleTime: 60000 olarak ayarlanırsa, önbellekteki veriler 1 dakika süreyle güncel kabul edilir.

cacheTime:

  • cacheTime, bir sorgunun önbellekte kaç süre boyunca tutulacağını belirler. Yani, bu süre boyunca aynı sorgu tekrarlanırsa, önbellekteki veriler hemen kullanılır ve yeni bir ağ sorgusu yapılmaz.
  • cacheTime özelliği, sorgunun önbellekte ne kadar süre boyunca saklanacağını belirler, ancak staleTime gibi belirli bir süre içinde aynı sorgu tekrarlandığında arka planda gerçek bir sorgu yapılmasını sağlamaz.

Otomatik Yeniden Sorgulama

React Query’de otomatik yeniden sorgulama, belirli bir sorgunun belli aralıklarla otomatik olarak tekrarlanmasını ifade eder. Bu, uygulama durumu değiştiğinde veya belirli bir zaman aralığı geçtiğinde verilerin güncellenmesi ve güncel kalması için kullanışlıdır.

React Query’de otomatik yeniden sorgulamayı kullanmak için refetchInterval özelliği kullanılır. Bu özellik, bir sorgunun kaç milisaniye aralıklarla otomatik olarak tekrarlanacağını belirler. Aşağıda basit bir örnek bulunmaktadır:

import { useQuery } from 'react-query';

const fetchData = async () => {
// API'den veri çekme işlemi
};

const MyComponent = () => {
const { data, isLoading, error, refetch } = useQuery('myData', fetchData, {
refetchInterval: 10000, // 10 saniyede bir (milisaniye cinsinden) otomatik olarak tekrarla
});
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
{/* Veri kullanma */}
</div>
);
};

Bu örnekte, refetchInterval özelliği kullanılarak sorgu, her 10 saniyede bir otomatik olarak tekrarlanacaktır. Bu sayede, belirli aralıklarla veri güncellenecek ve uygulamanızın her zaman güncel verilere sahip olmasını sağlayabilirsiniz.

refetchInterval özelliğini kullanırken, aynı zamanda manuel olarak da refetch fonksiyonunu çağırabilirsiniz. Örneğin, bir butona tıklandığında veya bir olay gerçekleştiğinde veriyi yeniden çekmek istiyorsanız, refetch fonksiyonunu çağırarak sorguyu manuel olarak başlatabilirsiniz.

--

--