React Query’e Genel Bir Bakış

Karmaşık API sorgularını ve state yönetimini kolaylaştıralım.

SHFT
4 min readFeb 17, 2023
React Query
React Query

Merhaba, bu yazımızda React ve React Native ile yazdığımız projelerde API isteklerini basit ve verimli bir şekilde yönetmemizi sağlayan React Query’den ve SHFT’de nasıl kullandığımızdan bahsetmek istiyoruz.

React Query v4 versiyonu ile birlikte ismi TanStack Query oldu ve diğer frameworkler için de kullanılabilir hale geldi ama biz bu yazıda React tarafına odaklanacağız.

React Query Nedir?

Öncelikle React Query’i, React uygulamalarında yaptığımız HTTP isteklerini yöneten ve bu istekler sonucunda da dönen verileri uygulama içerisinde yönetmemizi kolaylaştıran bir kütüphane olarak tanımlayabiliriz.

Peki, özellikle React ile yazılan uygulamalarda neden böyle bir kütüphane kullanma ihtiyacı duyuyoruz ve nasıl problemler yaşıyoruz bunu konuşalım.

Problemler vs React Query

React ile yazılan uygulamalarda karşımıza çıkan ilk problemlerin uygulama içerisindeki bileşenlerin sunucu tarafından ihtiyaç duyduğu veriyi nasıl alacağı ve aldığı veriyi nasıl yöneteceği ile ilgili olduğunu söyleyebiliriz. Çünkü React’in sağlamak istediği esnek mimariye uygun olarak bu konuda standart bir konsepti bizlere dayatmaması her React projesinde farklı farklı yaklaşımlar görmemize sebep oluyor.

Bir sonraki aşamalarda ise karşımızda sorgudan dönen hataların idare edilmesi, yükleme ekranları veya caching gibi kullanıcı üzerinde bırakacağımız etkiyi de belirleyecek yeni problemleri de görmeye başlıyoruz.

İşte React Query, uygulama boyunca daha stabil yapılar kurmamıza yardım ederken yukarıdakiler gibi birçok problemi de daha az ve daha okunabilir kodlar yazarak çözmemizi sağlıyor.

React Query’nin Avantajları

1. Basitleştirilmiş Polling: WebSocket gibi özel protokollerin olmadığı durumlarda arka planda veriyi periyodik bir şekilde almak için bir API’ye sürekli bağlı kalmak isteyebiliriz. Bu gibi kullanımlar için React Query’de useQuery ile kullandığımız refetchInterval ayarı bu işlemleri kolayca yapmamıza olanak sağlıyor.

2. Caching ve Garbage Collection: React Query’de cacheTime özelliğini kullanarak sunucudan dönen verileri önbelleğe alabilir ve staleTime özelliğiyle de birlikte bu verilerin geçerlilik süresini ayarlayarak API’ye atacağımız istekleri optimize edebiliriz. Bir sorguyu kullanan bileşenlerin bağlantısı kesildiğinde veya cache süresinin bitimiyle birlikte React Query kullanılmayan verileri bizim için tamamen siliyor olacak.

3. Koşullu Sorgular: React Query’de en çok kullandığımız özelliklerden biri olarak enabled ayarını sayabiliriz. Bir sorguya enabled ayarı olarak boolean bir değer geçtiğimizde o sorgunun belli bir koşul gerçekleştiğinde çalışmasını sağlayabiliyoruz.

4. Hooks: React Query’de hookların GET ve POST işlemlerine göre useQuery ve useMutation olarak birbirinden ayrılması ve bu hooklardan dönen değerlerin bu işlemlere göre değişmesi hem daha anlaşılabilir kodlar yazmamıza hem de işleme göre isteği daha iyi takip edebilmemizi sağlıyor.

5. DevTools: React Query ile birlikte gelen DevTools sayesinde geliştirme sırasında uygulama içerisindeki tüm sorgular hakkında detaylara ulaşabiliyoruz. Bu da geliştirme esnasında mevcut sorguların durumuna daha da hakim olmamızı sağlıyor.

Ufak Bir Karmaşa: Cache Time ve Stale Time

İlk kullananlar için cache yönetiminde cacheTime ve staleTime biraz kafa karıştırıcı olduğunu söylemek mümkün.

cacheTime: React Query’de bir sorguda varsayılan olarak 5 dakika olarak belirlenir ve bir sorgudan dönen cevabın önbellekte tutulma süresini ifade eder.

staleTime: Önbellekte tuttuğumuz verinin API’ye istek atarak ne kadar sıklıkla güncelleneceğini ifade eder diyebiliriz. Varsayılan olarak 0 geldiği için React Query önbellekte tutulan verinin hemen güncellenmesi gerektiğini düşünür.

Eğer sorgu sırasında bir cacheTime ve staleTime ayarlamadıysak, React Query cacheTime’ı 5 dakika ve staleTime’ı 0 olarak ayarlar. Bu durumda kullanıcıya önbellekte varsa yükleme ekranı yerine bir önceki veriyi göstermeye devam ederiz ama staleTime 0 olduğu için React Query önbellek içerisinde tutulan verinin güncelliğinin hemen bittiğini düşünür ve arka planda istek atıp veriyi tazelemeye devam eder.

API’ye sürekli istek atmayı önlemek için staleTime değerini geçebiliriz ama burada da dikkat etmemiz gereken konu cacheTime süresini de verdiğimiz staleTime süresine göre ayarlamak olacak.

Nasıl Kullanıyoruz?

1. İlk Adım: Global Tanımlama

Öncelikle React Query’i projeye dahil edelim.

npm i react-query 
##ya da
yarn add react-query

Sonrasında bileşenlerimizin QueryClient instance’ına erişebilmesi için uygulamamızı QueryClientProvider ile sarmalamamız gerekiyor.

// App.tsx

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

const queryClient = new QueryClient();

function App({ Component, pageProps }: AppProps) {
return (
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}

export default App;

Burada kullandığımız ReactQueryDevtools bileşenini tarayıcı üzerinde geliştirici arayüzüne erişmek için kullanıyoruz.

2. Custom API Hook Oluşturma

Biz uygulama boyunca gerçekleştireceğimiz HTTP isteklerini oluşturduğumuz custom hook’ların yardımıyla yapıyoruz. Bu sayede API isteklerimizi hem tekrar kullanımlara uygun hale getiriyoruz hem de kodumuzun okunabilirliğini arttırıyoruz.

//useGetTodos.ts

import axios from 'axios';
import { useQuery } from 'react-query';

export default function useGetTodos({ params = {}, ...props }: ApiQueryHookPropTypes): ApiQueryHookReturnTypes {
return useQuery(
['useGetTodos'],
() => axios.get('/todos', { params }).then((res) => res.data),
props
);
}

Yazdığımız custom hook’a yakından bakmak gerekirse, ilk olarak React Query’de GET isteklerimizi yönetmemizi sağlayan useQuery’e verdiğimiz parametreleri konuşabiliriz.

useQuery ilk parametre olarak bizden bu sorguyu diğerlerinden ayırmak ve kendi içerisinde tanımlamak için bir queryKey dizisi istiyor. React Query, caching işlemlerini bu queryKey dizisi üzerinden yönetirken biz de bu queryKey sayesinde hem DevTools üzerinden sorgumuzun durumunu kolaylıkla inceleyebiliyoruz hem de queryClient instance’ı üzerinden bu sorgu özelinde ekstra işlemler yapabiliyoruz. İkinci parametre de ise sorguyu gerçekleştirecek fonksiyonu ve son olarak da sorgu sırasında özel olarak kullanmak istediğimiz useQuery ayarlarını geçmek için bir obje iletiyoruz.

Ayrıca GET isteği için verebileceğimiz parametreleri de params olarak verebiliriz. Aynı şekilde bu params içerisinden gelen değerleri caching işlemlerini yönetmek için queryKey dizisine de verebiliriz.

Custom API Hook ile GET İsteği Örneği

 const { data, isLoading, isError, refetch } = useGetTodos({
params: {},
onSuccess: () => {},
onError: () => {},
});

3. Mutation

React Query’de POST, PATCH ve DELETE işlemlerini yönetmek için useMutation’ı kullanıyoruz. Mutation işlemleri için de aynı şekilde bir custom hook yapıp daha sonra bileşenlerimiz içerisinde bu hook aracılığıyla mutate işlemlerini gerçekleştiriyoruz.

//usePostTodos.ts

export default function usePostTodos(props?: ApiMutationHookPropTypes): ApiMutationHookReturnTypes {
return useMutation(
(data: TodoType) =>
axios.post('/todos', data).then((res) => res.data),
props
);
}

Custom API Hook ile POST İsteği Örneği

 const { mutate, isLoading, isSuccess } = usePostTodos({
onSuccess: () => {},
onError: () => {},
});

function handleCreatePost(data: TodoType) {
mutate(data);
}

Sonuç

React Query ile ilgili temel konulardan, avantajlarından ve kullanımlarımızdan bahsettik. Biz şu an Github’da 32 binden fazla starı olan React Query’i ekip olarak projelerimizde severek kullanıyoruz ama siz farklı alternatiflere bakmak isterseniz SWR ve RTK Query kütüphanelerini de inceleyebilirsiniz.

Gelecek yazılarda görüşmek dileğiyle, teşekkürler 🙂

Soner Gönençler | Frontend Team Lead

--

--