داستان از جایی شروع شد که برای مدیریت و ساخت Redux اپلیکیشن دنبال best practice ای بودم، که بتونم با اون دیتای گرفته شده از API ها و اطلاعات ورودی کاربر به اپلیکیشن رو، به خوبی داخل Redux مدیریت کنم. پس مثل همیشه دست به سرچ شدم تا best practice ایدهآل رو پیدا کنم.
متاسفانه یا خوشبختانه روش ایدهآلی برای پیدا سازی APIها داخل ریداکس نیست؛ اما طبق داکیومنت برای best practice گفته شده از redux-toolkit استفاده بشه. بعد از کلی گشتن، به روش جدید و جالبی برای مدیرت State های اپلیکشن برخوردم؛ توی این روش دیگه خبری از مدیریت کردن دیتای گرفته شده از API ها داخل Redux نیست.
توی این روش State های ما به دو بخش تقسیم میشه: Client State و Server State .Client State دیتای global ای هست که از کاربر گرفته میشه، مثل theme, language و غیره. Server State دیتایی هست که به واسطه API کالها وارد اپلیکیشن میشه.
مثل Redux که ابزاری برای مدیریت Global State هست، برای مدیریت Server state هم به ابزار خاص خودش نیاز داریم که از معروفترین این ابزارها میشه به React-Query و SWR اشاره کرد. توی این مقاله به چگونگی اضافه کردن React-query و ویژگیهای مهم اون در اپلیکیشن React میپردازیم.
مهمترین ویژگیای که این ابزارها به پروژههای Reactای میدن: حذف کدهای تکراری (boilerplate) برای مدیریت کردن هر ریکوست، resolve و reject شدن اونها توی reducer هست. در کنار این مزایا، ویژگیهای جذاب دیگهای هم مثل:
ویژگی های این ابزار فقط به موارد بالا خلاصه نمیشه. علاوه بر این، دارای هوکهای (hook) پیش ساخته مثل برای infinite scroll , pagination و کلی هوک های دیگه برای شرایط خاصتر داره. دیگه مقدمه چینی کافیه بریم دست به کد بشیم.
ترمینال خودتون رو باز کنید و package رو با استفاده از کدهای زیر نصب کنید:
npm i react-query or yarn add react-query
بعد از نصب package نیاز به ساخت QueryCilent و QueryClientProvider هست.
import { QueryClient, QueryClientProvider } from 'react-query' // Create a client const queryClient = new QueryClient() function App() { return ( // Provide the client to your App <QueryClientProvider client={queryClient}> <App/> </QueryClientProvider> ) }
برای اینکه بتونیم از React-query توی تمام اپلیکیشن استفاده کنیم نیاز هست داخل فایل app.js کد بالا رو وارد کنیم. با استفاده از فانکشن QueryClient یک نمونه client provider جدید برای ما ساخته میشه و با احاطه کردن (wrap) کامپوننت QueryClinetProivder دور کامپوننت App ، Server State Mangement خودمون رو می سازیم.
برای دیدن دیتای ذخیره شده و مابقی اطلاعات می تونیم از devtools استفاده کنیم، فقط کافیه کد زیر به عنوان فرزند به کامپوننت QueryClientProvider اضافه بشه:
import { ReactQueryDevtools } from 'react-query/devtools' function App() { return ( <QueryClientProvider client={queryClient}> <App/> <ReactQueryDevtools /> </QueryClientProvider> ) }
پس از اضافه کردن devtools لوگو react-query به صورت پیش فرض پایین سمت چپ مرورگر شما ظاهر میشه و با کلیک بر روی لوگو devtools باز میشه.
هوک useQuery برای گرفتن اطلاعات (GET) و ذخیرهی دیتا به واسطه یک uniqueQueryKey منحصر به فرد داخل caching system هست. یا به زبان ساده، دیتا تحت یک اسم خاصی در caching system ذخیره میشه. این هوک، سه پارامتر دریافت میکنه:
import { useQuery } from 'react-query'; const fetcher = () => fetch(url).then(res => res.json()) function Component() { const { data, error, isLoading , ...rest } = useQuery('posts', fetcher , options) return ( // jsx ) }
به طور کلی توی کد بالا هوک useQuery یه uniqueQueryKey به نام posts قرار دادیم، که نتیجه فانکشن fetcher که یک promise هست رو داخل اون قرار بده. options هم یک پارامتر اختیاری هست که برای تغییرات تنظیمات پیشفرض میشه از اون استفاده کرد.
در اخر هم میتونیم با object destructuring اطلاعات خروجی مورد نظرمون از useQuery رو گرفته و استفاده کنیم.
به عنوان مثال، هوکهای useQuery و useInfiniteQuery رو بعد از گرفتن دیتا، ذخیره و cache کردن در اپلیکیشن به عنوان دیتای قدیمی یا تاریخ گذشته ثبت میکنه. یا به اصطلاح stale شده و وقتی به این شکل باشه، react-query تلاش می کنه تا در اولین فرصت دیتا رو دوباره از اون API کال گرفته و مقایسه کنه؛ که آیا دیتا بروز شده یا نه. اگه دیتا تغییری نکرده باشه که از دیتای cache شده استفاده میکنه و در غیر اینصورت، اطلاعات جدید رو گرفته و جایگزین اطلاعات cache شده میکنه.
و اما قسمت مهم اینه که، کی و در چه صورتی اطلاعات رو مجدداً میگیره:
توی فاز دولوپ کردن حواستون به مورد شماره ۲ باشه، چون ممکنه زیاد اتفاق بیفته. react-query تنظیمات پیشفرض دیگهای هم برای سیستم garbage collection داره که می تونید اینجا بیشتر بخونید.
توی این مقاله تلاش کردم تا مفاهیم اولیه و یکی از هوکهای مهم این پکیج رو معرفی کنم. اطلاعات بیشتر رو می تونید از داکیومنت اصلی بخونید. خالی از لطف نیست که به پکیج رقیبش swr، که vercel نوشته هم یه نگاهی بندازید.