ریکت کوئری

با ریکت کوئری کنترل بیشتری روی داده های دریافتی از سمت سرور داریم، میتوان داده های مورد نظر رو از 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 -> data1page=2 -> data2page=3 -> data3که اگه بخوایم این مثال رو برای سه درخواست به سرور درنظر بگیرم مقدار lastPage ما شامل data3 میشه و مقدار allPage ما میشه هر سه مقدار data1, data2,data3 و همینطور خروجی getNextPageParam یک عدد هست ( در واقع یک شماره page رو ریترن میکنه) ک اون عدد میشه page بعدی ک باید queryFn فراخوانی کنه رو برمیگردونه ک این مقدار رو ما باید ست کنیم و توی ریترنش برگردونیمتوجه : مقدار pageParam از تابع queryFn: ({ pageParam = 1 }) => fetchPage(pageParam) ک در بار اول مقدارش رو میتونیم با 1 ست کنیم و برای بارهای بعد pageParam مقدار جدیدش رو از تابع getNaxtPageParam میگیره( که آخرین pageی ک باید فراخوانی بشه رو برمیگردونه)