ویرگول
ورودثبت نام
samira gheibipour
samira gheibipour
خواندن ۶ دقیقه·۲ سال پیش

ریکت کوئری


با ریکت کوئری کنترل بیشتری روی داده های دریافتی از سمت سرور داریم، میتوان داده های مورد نظر رو از api گرفت و اون رو کش(cache) میکنه و...

در واقع منطق ریکت کوئری میگه ک شما یه تابع fetcher به من بده ( مثل fetch ,axios ,... اون چیزی که میخواد یه تابع یک دیتا برگردونه) بقیه عملیات مثل کش کردن و آپدیت کردن و... با من.

در واقع ریکت کوئری میاد چیکار میکنه؟ میاد اول دیتا ما رو میگیره از api و بعد با همون key ک تعریف کردیم، دیتا رو با همون key کش میکنه و بعد نشون کاربر میده( توجه داشته باشید که اگه دفعه بعدی همون useQuery یا هر تابعی از react query رو با همون key صدا زد -> بصورت موازی که داره دیتا کش شده همون key رو نشون کاربر میده، میره دیتا رو از سرور میگیره و اگه دیتا تغییری نکرد ک هیچ کاری نمیکنه. اما اگه دیتا گرفته شده مغایرت داشت با دیتا کش شده( حتی یه کلمه اش) میاد کل دیتا رو جایگزین دیتا کش شده میکنه و نشون کاربر میده.)

ببینید از مزایای ریکت کوئری میشه به این اشاره کرد ک دیگه شما state اضافه ای مثل loading,data,error و اینا تعریف نمیکنید. یعنی چی؟

یعنی اینکه شما وقتی بصورت عادی یه Api رو کال میکنید

call api=>

setState loading=true;

setState data=fetch from data;

setState error="message error";

نیاز دارید به حداقل این نمونه stateها ک با استفاده از ریکت کوئری دیگه نیازی به تعریف این قبیل stateها ندارید و خودش هندل میکنه و هر زمان خروجی رو به ما میده


توجه: توجه داشته باشید که ریکت کوئری رو باید توی خود کامپوننت تعریفش کنید! یعنی نمیتونید توی یه فانشن تعریفش کنید و... باید توی خود root کامپوننت تعریفش کنید.


خب برای استفاده از ریکت کوئری ابتدا باید در اولین پیجی ک برنامتون فراخوانی میشه حالا یا app یا index پروژه تون این کانفیگ رو بزارید

(البته توجه داشته باشید ک باید @tanstack/react-query رو نصب کنید )

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

const queryClient = new QueryClient();

وQueryClientProvider رو اول کدهای ک نوشتید بزارید

<QueryClientProvider client={queryClient}></QueryClientProvider>

بعنوان مثال من توی فایل index.js م اومدم اینطور گذاشتم

import React from 'react';

import {AppRegistry} from 'react-native';

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

import App from './app/App';

import {name as appName} from './app.json';

const queryClient = new QueryClient();

const MyProject= () => (

<QueryClientProvider client={queryClient}>

<App />

</QueryClientProvider>

);

AppRegistry.registerComponent(appName, () => MyProject);

خب حالا نمونه استفاده از useQuery رو اول میگم

توی جای ک میخواید استفاده کنید(منظورم کامپوننت یا صفحه و...)

اول importش میکنید

import { useQuery } from '@tanstack/react-query'

سپس

const { isLoading, isError, data, error } = useQuery({queryKey: ['todos'],queryFn: fetchTodoList,})

اینطور استفاده میکنیم، ک حالا به توضیح تک تکشون میپردازیم

فقط دقت داشته باشید ک

خروجی useQuery بیشتر از این 4 مورد هست ک از پایین میتونید بقیه موارد رو اضافه یا کم کنید،و همینطور ورودیش

https://tanstack.com/query/v4/docs/reference/useQuery

ک در ابتدا وقتی تو صفحه میخواید لودش کنید اول isLoading مقدارش trueهست تا هر موقع دیتا گرفت این isLoading مقدارش فالس میشه

یعنی خود ریکت کوئری متناسب خروجی هرکدوم رو ست میکنه ک ما با این خروجیا میتونیم دیتا مورد نظرمون رو به کاربر بگیم

مثلا میتونیم بزاریم

isLaoding? (</Loading>):(data or error handel)

یعنی اگه loading مقدارش true بود میگیم به کاربر loading رو نشون بده اگه نه بره همینطور error یا data رو هندل کنه و متناسب باهاش داده مورد نظر رو به کاربر نشون بده

اما آرگومانهای ورودی:

queryKey

این مقدار برای هر useQuery که ما میسازیم باید uniqe باشه(یعنی خاص و غیر تکراری چون دیتا دریافتی از سرور با این key ذخیره میشه) و همینطور ک توی مثالش هم مشخصه باید رشته باشه

و آرگومان دوم

queryFn

همون تابع fetcherی ک از قبل ساختیم

و همینطور ما option های اضافه تری هم میتونیم داشته باشیم

مثلا ما نمیخوایم با لود صفحه useQuery ما صدا زده بشه میخوایم وقتی روی یه دکمه(یا باتن) بزنیم این useQuey فراخوانی بشه خب از enable=fale استفاده میکنیم

برای مثال من اینطور نوشتم

const {isLoading,isInitialLoading,isError,data,error,refetch,isFetching,} = useQuery({

queryKey: ['useInventoryList'],queryFn: () =>getInventoryList({RowFrom:0,RowCount:10}),

enabled: false,

});

ک هر موقع میخواید صداش بزنید باید refetch رو صدا بزنید

و همینطور میتونید تایم کش رو کم و زیاد کنید و آپشنهای زیاد دیگه ای ک خودتون بقیه داکیومنت رو بخونید و تست کنید

هدف من یه سمپل ساده از useQuery بود


اما یه هوک دیگه از ریکت کوئری useQueryClient هست (البته یکی از کاربرداش ک من کار کردم میدونم اینه) که داریم یه useQuery رو مثلا با page=1 صداش میزنیم و توی بطن ماجرا هم میخوایم همزمان page=2 رو هم صدا بزنیم

بعنوان مثال

queryClient=useQueryClient();

queryClient.prefetchQuery(queryKey,queryFn)

در واقع میره دیتا page بعد رو هم میگیره و کش میکنه ک برای دفعات بعدی میخوایم page بعد رو صدا بزنیم سرعت لودش سریع باشه



اما هوک دیگه useInfiniteQueryهست ، ما گاهی یک Api داریم ک علاوه بر page=1 باز به page قبل و بعدش نیاز داریم در واقع دیتا همراه با paggination بیاد ک از این هوک استفاده میکنیم ک در واقع دیتا قبل و بعدی رو هندل میکنه و چک میکنه ک آیا page بعدی دیتا داره یا نه و...

نمونه استفاده ازش

const {fetchNextPage,fetchPreviousPage,hasNextPage,hasPreviousPage,isFetchingNextPage,isFetchingPreviousPage,...result} = useInfiniteQuery({queryKey,queryFn: ({ pageParam = 1 }) => fetchPage(pageParam),...options,getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,})

https://tanstack.com/query/v4/docs/reference/useInfiniteQuery

که پارامترهای ورودی باز مشخصه و خروجی

اما یه توضیح لازم هست بدم درمورد

getNextPageParam

که دوتا ورودی داره این تابع و یک خروجی

ک ورودی اولش ک به اسم lastPage هست در واقع مقدار آخرین دیتا از آخرین pageی که ما به سرور ریکوست دادیم برای گرفتن دیتا api رو درون خودش نگه میدارد ( بنظرم بهتره اسمش رو به DataOfLastPage تغییر بدیم خوانایی و مفهوم رو بهتر میرسونه، این نظر شخصی منه! چون وقتی میگیم lastPage توی ذهن ما یه عدد تداعی میشه تا یه دیتا)

ورودی دوم allPage که داخلش همه دیتاهای همه pageهای ک تا حالا ریکوست داده به سرور رو داره(یعنی همه pageهای تا حالا دیتا گرفته رو داخش داره)

page =1 -> data1

page=2 -> data2

page=3 -> data3

که اگه بخوایم این مثال رو برای سه درخواست به سرور درنظر بگیرم مقدار lastPage ما شامل data3 میشه و مقدار allPage ما میشه هر سه مقدار data1, data2,data3

و همینطور خروجی getNextPageParam یک عدد هست ( در واقع یک شماره page رو ریترن میکنه) ک اون عدد میشه page بعدی ک باید queryFn فراخوانی کنه رو برمیگردونه ک این مقدار رو ما باید ست کنیم و توی ریترنش برگردونیم

توجه : مقدار pageParam از تابع queryFn: ({ pageParam = 1 }) => fetchPage(pageParam) ک در بار اول مقدارش رو میتونیم با 1 ست کنیم و برای بارهای بعد pageParam مقدار جدیدش رو از تابع getNaxtPageParam میگیره( که آخرین pageی ک باید فراخوانی بشه رو برمیگردونه)

ریکت کوئریreact queryusequeryreactreact native
شاید از این پست‌ها خوشتان بیاید