آموزش ریاکت کوئری (React Query) – هوک useQuery و useMutation

درود بر کاربران گرامی آکادمی راهکارینو، با یک آموزش دیگه در زمینه لایبرری ری اکت در خدمتتان هستیم.
مقدمه و معرفی کتابخانه React Query:
ری اکت (Reactjs) بدون شک یکی از قوی ترین کتابخانه های نوشته شده توسط جاوا اسکریپت می باشد. Reactjs امکانات بسیاری را در زمینه توسعه رابط کاربری (UI) در اختیار برنامه نویسان فرانت اند قرار می دهد. اما در عین حال، ری اکت یک سری کمبودها و نقاط ضعفی هم دارد. مانند مدیریت state و دریافت و کش کردن داده های دریافت شده از سرور و…
کتابخانه React Query برای رفع این مشکلات معرفی شده است. توسط این کتابخانه محبوب و قدرتمند می توان کنترل بیشتری روی داده های دریافتی از سمت سرور داشت. توسط ریکت کوئری، می توان داده های موردنظر را از API دربافت کرد (fetch) آنها را کش کرد (cache) و بروزرسانی (update) کرد.
می توان گفت اغلب وب اپلیکیشن ها نیاز دارند تا توسط api به سرور درخواست دهند و دیتای موردنظر خود را دریافت کنند و داده های دلخواه را به آن ارسال کنند و داده های موجود را update یا delete کنند. بنابراین نیاز به ابزاری که بتواند تمام این کارها را انجام دهد و داده ها را مدیریت کند بسیار احساس می شود.
بعنوان یک دولوپر فرانت اند باید قبل از شروع توسعه اپلیکیشن به سوالات زیر پاسخ دهید:
- در زمانی که کاربر منتظر دریافت داده از سرور است چه چیزی باید به او نمایش دهیم؟
- اگر در این حین خطایی رخ دهد چه کاری باید انجام شود؟
- چطور می توان داده های سمت کلاینت را با سرور هماهنگ کرد و تطابق داد؟
- اگر اتصال اینترنت کاربر ضعیف باشد چه اتفاقی برای اپلیکیشن خواهد افتاد؟!
- و غیره…
بنابراین وقتی در اپلیکیشن خود با داده های ناهمگام (async) سر و کار داریم و میخواهیم عملیات CRUD را روی آنها بطور مدام انجام دهیم، بهترین گزینه استفاده از کتابخانه ری اکت کوئری (React-Query) خواهد بود.
در این آموزش، قصد داریم نحوه نصب و کار با کتابخانه React Query را آموزش دهیم. همراه ما بمانید…
(برای تعامل با سرور از jsonplaceholder استفاده شده است)
پیش نیازهای این دوره:
برای اینکه بتوانید بیشترین بهره را از این مقاله آموزشی ببرید، بهتر است موارد زیر را در نظر بگیرید:
- تسلط نسبی بر روی فانکشن کامپوننت های ری اکت و کار با هوک ها الزامی است.
- آشنایی با نحوه کار با REST API و دریافت داده از سرور در جاوا اسکریپت.
- اطمینان از نصب و فعال بودن Node.js روی سیستم عامل.
> مطالعه مقاله “آشنایی با هوک های useEffect و useState” پیشنهاد می شود.
> مطالعه مقاله “آموزش مقدماتی کتابخانه React js” پیشنهاد می شود.
برخی از مزایای ریکت کوئری (React Query):
- می توان تعداد درخواست های مجدد به سرور را تعیین کرد. یعنی اگر درخواست ما با خطا مواجه شد می توانیم تعداد تلاش های بعدی را برای دسترسی به دیتای سرور مشخص کنیم.
- امکان refetch کردن دیتا از سرور را بصورت دستی یا manual فراهم می کند. با استفاده از قابلیت refetch در هوک useQuery.
- امکان کش کردن (cache) دیتا در اپلیکیشن های سنگین و پیچیده می تواند تا حد زیادی بر روی کارایی (performance) برنامه تاثیر مثبت داشته باشد.
- در هر بار ارسال درخواست به سرور، امکان prefetch کردن داده وجود دارد. در ادامه مقاله مفهوم prefetching بیشتر توضیح داه خواهد شد.
> مطالعه مقاله “روش های افزایش کارایی اپلیکیشن های React” پیشنهاد می شود.
نصب ری اکت کوئری (Install React Query):
به منظور ارتباط با سرور در این مقاله، از jsonplaceholder و بخش ToDoبهره خواهیم برد. برای شروع کدنویسی، نیاز است ابتدا یک وب اپلیکیشن ری اکتی را توسط دستور زیر ایجاد کنیم:
npx create-react-app react-query-demo #or yarn create react-app react-query-demo
سپس به منظور ارسال درخواست به سرور می خواهیم از کتابخانه axios استفاده کنیم. آموزش کامل نحوه استفاده از لایبرری axios را می توانید در این مقاله مطالعه کنید. همچنین کتابخانه react query را باید نصب کنیم. به شکل زیر:
npm i react-query axios #or yarn add react-query axios
در نهایت برای اجرای پروژه دستور npm start را اجرا خواهیم کرد. اپلیکیشن در آدرس http://localhost:3000 قابل مشاهده خواهد بود.
نکته: طبق داکیومنت سایت tanstack برای نصب نسخه های جدید ری اکت کوئری (ورژن 4 به بعد) باید از دستورات زیر استفاده کرد:
$ npm i @tanstack/react-query # or $ pnpm add @tanstack/react-query # or $ yarn add @tanstack/react-query
پیکربندی و تنظیمات React Query:
پس از نصب کتابخانه react query به منظور استفاده از آن در پروژه خود نیاز است تمام کامپوننت های اپلیکیشن را داخل QueryClientProvider احاطه کنیم. در این حالت، تمام کامپوننت های برنامه، به هوک useQuery و همچنین هوک useMutation دسترسی خواهند داشت.
نحوه تعریف QueryClientProvider در فایل index.js به شکل زیر است:
import React from 'react' import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import { QueryClient, QueryClientProvider } from "react-query"; const queryClient = new QueryClient(); ReactDOM.render( <QueryClientProvider client={queryClient}> <App /> </QueryClientProvider>, document.getElementById('root') );
دریافت داده از سرور توسط useQuery:
همراهان آکادمی راهکارینو، تفاوت اصلی بین دریافت داده (data fetching) به روش کلاسیک (مانند هوک useEffect) و روش React Query عملیات PreFetching می باشد. به این معنا که هر بار که درخواست دریافت داده از سرور ارسال می شود، react query ابتدا داده ای که از قبل prefetch شده است را بر می گرداند و سپس داده جدید دریافت (fetch) می شود.
اگر داده قدیم با داده جدید یکسان باشد، ری اکت کوئری همان داده قدیم را نمایش خواهد داد و صفحه مجددا بارگذاری (reload) نخواهد شد. اما در روش متداول قبلی یعنی استفاده از هوک useEffect با هر بار درخواست از سرور، یکبار صفحه رفرش خواهد شد. چه دیتا تغییر کرده باشد و چه تغییر نکرده باشد.
برای مشاهده نحوه کار با کتابخانه react-query بصورت عملی، یک فولدر در src بسازید بنام components و سپس یک فایل بنام Posts.js در آن تعریف کنید. عملیات fetch را در این فایل انجام می دهیم.
ابتدا باید دستورات import زیر را در بالای فایل تعریف کنیم:
import React from 'react' import {useQuery} from 'react-query' import axios from 'axios'
به منظور دریافت داده از سرور jsonplaceholder ابتدا نیاز است یک تابع ناهمگام (مثلا بنام fetchPosts) به شکل زیر تعریف کنیم:
async function fetchPosts(){ const {data} = await axios.get('https://jsonplaceholder.typicode.com/posts') return data }
و در مرحله بعد، از هوک useQuery به شکل زیر استفاده می کنیم:
const {data, error, isError, isLoading } = useQuery('posts', fetchPosts)
مشاهده می شود که هوک useQuery دو آرگومان می گیرد. اولین آرگومان کلید یا key است که برای کش کردن (caching) بکار می رود و مقدارش دلخواه است ولی باید منحصر بفرد (unique) باشد. دومین آرگومان تابع ناهمگامی است که در آن HHTP Request تعریف می شود. چهار پارامتر data, error, isError, isLoading را می توان از این هوک استخراج کرد.
مشخص است که data شامل دیتای بازگشتی از سرور می باشد. error یک آبجکت است که errpr.message شامل پیغام خطای احتمالی است. isError یک مقدار بولین است که بیانگر خطا داشتن یا نداشتن درخواست ما است. و در نهایت isLoading نیز یک مقدار بولین است که برای نمایش یک لودینگ به کاربر در زمان واکشی دیتا از سرور بکار می رود.
سپس می توان از داده های فوق به شکل زیر در پروژه استفاده کرد:
if(isLoading){ return <div>Loading...</div> } if(isError){ return <div>Error! {error.message}</div> } return( <div className='container'> <h1>Posts</h1> { data.map((post, index) => { return <li key={index}>{post.title}</li> }) } </div> )
نکته 1: برای راحتی کار توسعه دهندگان، کتابخانه react query یک ابزاری بنام react query devtools ارائه می دهد. در این مقاله می توانید بیشتر بخوانید.
نکته 2: همانطور که مشاهده کردید، با استفاده از ری اکت کوئری، برای fetch کردن دیتا از سرور، دیگر نیازی به هوک useEffect و همچنین مدیریت کردن حالت لودینگ و خطای درخواست نخواهد بود. کتابخانه React Query تمام این کارها را بطور خودکار برای ما انجام می دهد.
نکته 3: بصورت پیش فرض، وقتی از لایبرری react query برای fetch کردن دیتا از api استفاده می کنیم، با عوض کردن تب مرورگر، دیتا مجددا از سرور فچ می شود. این قضیه می تواند در برخی موارد کاربرد داشته باشد. مثلا در سایت های خبری که اخبار به شکل لحظه ای منتشر می شود. اما برای کاربردهای عادی، ممکن است مشکل ساز باشد. برای غیرفعال کردن refetch در هر بار فوکوس روی تب مرورگر، می توان تنظیمات پیش فرض QueryClient را به شکل زیر تغییر دهیم:
const client = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, }, }, });
نکته 4: امکان جالب دیگری که ری اکت کوئری دارد اینست که می توان در بازه های زمانی مشخص، دیتای موردنظر را از سرور دریافت کند. بعنوان مثال در قطعه کد زیر، هر 10 ثانیه یکبار درخواست get بصورت اتوماتیک انجام می شود:
const client = new QueryClient({ defaultOptions: { queries: { refetchInterval: 10000, }, }, });
نکته 5: قابلیت دیگری که react-query دارد کش کردن دیتای دریافتی است. در کد زیر، گفتیم که زمان caching یک شبانه روز یا 24 ساعت باشد:
const queryClient = new QueryClient({ defaultOptions: { queries: { cacheTime: 1000 * 60 * 60 * 24, // 24 hours }, }, })
درخواست POST توسط هوک useMutation:
بر خلاف هوک useQuery که فقط برای fetch کردن دیتا از سرور به کار می رود (متد GET)، از هوک useMutation می توان برای Update و Delete و Create کردن دیتا روی سرور استفاده کرد (متدهای PUT و DELETE و PATCH و POST).
در این مقاله فقط ارسال داده به سرور توسط متد POST را بررسی خواهیم کرد. به این منظور یک فایل بنام Post.js در فولدر components بسازید و دستورات import زیر را در بالای این فایل درج کنید:
import React, {Fragment, useState} from 'react' import { useMutation } from 'react-query' import axios from 'axios'
در ادامه باید یک تابع ناهمگام (async function) برای ارسال درخواست POST تعریف کنیم. به این صورت:
const sendPost = async (data) => { const response = await axios.post('https://jsonplaceholder.typicode.com/posts', data); return response.data; };
سپس از هوک useMutation به شکل زیر استفاده کنید:
const { mutate, isLoading, isError, error } = useMutation(sendPost, { onSuccess: data => { setPosts([...posts, data]); alert("پست با موفقیت ثبت شد"); }, onError: () => { alert("ثبت پست با خطا مواجه شد"); }, onSettled: () => { } });
در نهایت در رویداد onClick دکمه “ارسال پست” تابع mutate را به شکل زیر صدا بزنید:
mutate({ title: "post title sample", body: "post description sample", userId: 1, postDate: new Date() });
توضیح کدهای فوق:
ابتدا یک تابع ناهمگام یا async بنام sendPost تعریف کرده ایم که دیتای ارسالی را بعنوان آرگومان ورودی می گیرد و توسط متد post در axios آن را به سرور ارسال می کند و دیتای بازگشتی را در قالب response.data بر می گرداند.
سپس توسط هوک useMutation ادامه فرآیند ارسال درخواست HTTP POST را انجام می دهیم. این هوک دو آرگومان دارد که اولین آرگومان، تابع sendPost می باشد (در واقع تابع ناهمگامی که عملیات post کردن دیتا را بر عهده دارد). دومین آرگومان یک آبجکت است که شامل متدهای onSuccess و onError و onSettled می باشد. در صورتی که درخواست POST با موفقیت انجام شود، متد onSuccess اجرا خواهد شد و می توان در این متد، پیغام موفقیت آمیز بودن ارسال پست را به کاربر نمایش داد. اما اگر این عملیات با خطا مواجه شود، onError اجرا می شود و پیغام خطا را در این قسمت نمایش می دهیم.
هوک useMutation همانند هوک useQuery چهار مقدار بر می گرداند. mutate, isError, error, isLoading با این تفاوت که هوک useQuery مقدار data را return می کند اما هوک useMutation مقدار mutate را.
در ادامه باید از همین مقدار mutate برای ارسال دیتای موردنظر استفاده کنیم. بنابراین در رویداد onClick دکمه ارسال فرم، تابع mutate را به همراه آبجکت موردنظر صدا می زنیم.
در تصویر زیر یک شمای کلی از برنامه را مشاهده می کنید:
نتیجه گیری:
توسعه وب اپلیکیشن توسط کتابخانه Reactjs می تواند در ابتدا ساده و سریع انجام شود اما وقتی به مراحل تعامل با سرور و دریافت (Fetch یا GET) دیتا از سرور و نیز ارسال داده به سرور (POST) می رسیم، اپلیکیشن ما می تواند پیچیده تر شود و همچنین ممکن است کارایی و سرعت برنامه نیز پایین بیاید. اما با استفاده از کتابخانه React Query می توان توسعه درخواست های ناهمگام یا async را به این کتابخانه سپرد و خود این کتابخانه تمام سناریوها را برای ما مدیریت می کند. لایبرری ری اکت کوئری امکانات و ویژگی های دیگری نیز دارد. مانند کش کردن دیتا و prefetching و صفحه بندی دیتای دریافتی از سرور و…
ما در این مقاله سعی کردیم دو مبحث مهم ارسال درخواست های GET و POST را بطور کامل توسط کتابخانه React Query آموزش دهیم و در بخش دوم مقاله یعنی آموزش پیشرفته React-Query مباحثی مانند Pagination یا صفحه بندی و نیز اسکرول بی نهایت (Infinite Scroll) را بررسی کرده ایم.
امیدوارم از این آموزش استفاده لازم را برده باشید. لطفا آن را با دوستان خود به اشتراک بگذارید و صفحه اینستاگرام ما را به نشانی rahkarino دنبال کنید. در صورتی که سوال یا پیشنهادی درباره این مقاله دارید در پایین همین بخش آن را مطرح کنید تا کارشناسان ما در اسرع وقت پاسخگوی شما باشند 🙂
مطالب زیر را حتما مطالعه کنید
2 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
عالی بود
اگر بدونید چقدر دنبال این نکته ۳ که گفتید گشتم تا پیدا کنم که نگو…
سلام دوست عزیز. خوشجالم که این مقاله مفید بوده براتون