ساخت قلاب ری اکت useFetch – از صفر تا صد

۶۳ بازدید
آخرین به‌روزرسانی: ۰۵ مهر ۱۴۰۲
زمان مطالعه: ۵ دقیقه
ساخت قلاب ری اکت useFetch – از صفر تا صد

قلاب‌ها (Hooks) ابزارهای بسیار مفیدی هستند که در ری‌اکت نسخه 16.8 اضافه شده‌اند. با استفاده از قلاب‌ها می‌توان کامپوننت‌های باحالت (Stateful) را بدون نوشتن کلاس ساخت. ری‌اکت دارای قلاب‌های زیادی از قبیل useState، useEffect ،useContext و موارد بسیار دیگر است. این قلاب‌ها برای بسیاری از کاربردهای عمومی مناسب هستند، اما نکته جالب‌تر آن است که شما می‌توانید خودتان نیز بسته به نیازهای خاص خود قلاب‌هایی بسازید. در این راهنما با روش ساخت قلاب ری اکت useFetch آشنا می‌شویم.

997696

طرز کار قلاب چگونه است؟

قلاب در واقع یک تابع است که به هر تعداد که لازم باشد آرگومان می‌گیرد و آن چه که لازم است به کامپوننت بازگشت یابد را بازمی‌گرداند.

در ادامه مثالی از ساده‌ترین قلاب ممکن را می‌بینید:

1function useYear() {
2  return new Date().getFullYear();
3}
4export default useYear;

همچنان که می‌بینید به نظر می‌رسد که یک تابع معمولی است. از آن می‌توان به صورت زیر استفاده کرد:

1// ...
2import useYear from "./useYear";
3function App() {
4  const year = useYear();
5  return (
6    <div className="App">
7      <h1>Year: {year}</h1>
8    </div>
9  );
10}
11// ...

این یک قلاب عالی است، اما در ادامه روی مسئله‌ای مفیدتر کار می‌کنیم.

ساخت یک قلاب useFetch

قلاب‌ها برای اجتناب از تکرار کردن کد در بخش‌های مختلف اپلیکیشن عالی هستند. یکی از کارهایی که مکرر در اپلیکیشن‌ها انجام می‌دهیم، واکشی کردن داده‌ها است. در ادامه روش نوشتن یک قلاب را با خصوصیت‌های زیر بررسی می‌کنیم:

  • بتواند داده‌ها را واکشی کند.
  • یک حالت بارگذاری را بازگشت دهد.
  • یک حالت خطا بازگشت دهد.

1. ایجاد یک قلاب ابتدایی که داده‌ها را واکشی کند

1import React, { useState, useEffect } from "react";
2const useFetch = (url, options) => {
3  const [response, setResponse] = useState(null);
4  useEffect(() => {
5    const doFetch = async () => {
6      const res = await fetch(url, options);
7      const json = await res.json();
8      setResponse(json);
9    }
10    doFetch();
11  }, []);
12  return response;
13};
14export default useFetch;

قلاب ما دو آرگومان می‌گیرد که یکی یک URL و دیگری یک شیء گزینه‌ها است. آرگومان گزینه‌ها می‌تواند شامل هر چیزی باشد که API نیتیو ()fetch به عنوان یک آرگومان دوم مورد استفاده قرار می‌دهد. این قلاب از useEffect برای واکشی کردن داده‌ها استفاده می‌کند و داده‌ها را در حالت پاسخ با استفاده از useState تعیین می‌کند.

توجه کنید که آرایه خالی به صورت آرگومان دوم useEffect ارسال می‌شود. بر اساس طراحی، useEffect زمانی تحریک می‌شود که کامپوننت نصب شود و همچنین زمانی که کامپوننت به روز شود تحریک خواهد شد. اما اگر بخواهیم آن را تنها یک بار اجرا کنیم useEffect یک آرگومان دوم می‌گیرد که می‌توان روی آرایه‌ای از متغیرها که می‌خواهیم مشاهده کنیم تنظیم کرد. با ارسال یک آرایه خالی مطمئن می‌شویم که useEffect تنها یک بار و در زمان نصب شدن، تحریک خواهد شد.

2. مدیریت خطاها

برخی اوقات مسائل آن چنان که برنامه‌ریزی‌شده پیش نمی‌روند و باید کاری کنیم که کامپوننت ما از این مسئله آگاه شود. کد خود را درون یک Try… Catch قرار می‌دهیم از useState برای ذخیره خطای بالقوه استفاده می‌کنیم:

1import React, { useState, useEffect } from "react";
2const useFetch = (url, options) => {
3  const [response, setResponse] = useState(null)
4  const [error, setError] = useState(null);
5  useEffect(() => {
6    const doFetch = async () => {
7      try {
8        const res = await fetch(url, options);
9        const json = await res.json();
10        setResponse(json);
11      } catch (e) {
12        setError(e);
13      }
14    };
15      doFetch();
16  }, []);
17  return { response, error };
18};
19export default useFetch;

3. بازگشت یک حالت بارگذاری

می‌خواهیم در زمان اجرای واکشی یک آیکون بارگذاری را در کامپوننت اصلی خود نمایش دهیم. همان طور که درمورد مدیریت خطا عمل کردیم این بار نیز حالت بارگذاری را اضافه می‌کنیم:

1import React, { useState, useEffect } from "react";
2const useFetch = (url, options) => {
3  const [response, setResponse] = useState(null)
4  const [error, setError] = useState(null);
5  const [loading, setLoading] = useState(false);
6  useEffect(() => {
7    const doFetch = async () => {
8      setLoading(true);
9      try {
10        const res = await fetch(url, options);
11        const json = await res.json();
12        setResponse(json);
13      } catch (e) {
14        setError(e);
15      } finally {
16        setLoading(false);
17      }
18    };
19    doFetch();
20  }, []);
21return { response, error, loading };
22};
23export default useFetch;

بسیاری از افراد این حالت را نادیده می‌گیرند اما Try… Catch یک گزاره final را به نام finally می‌گیرد. Finally صرف نظر از این که خطا باشد یا نباشد اجرا می‌شود و در این مورد نیز همین را می‌خواهیم. در زمانی که واکشی تمام شد، حالت بارگذاری را false می‌کنیم.

4. پاکسازی

اکنون در صورتی که درخواست کُند باشد و کامپوننت در زمان پایان یافتن درخواست ناهمگام unmount شده باشد چه باید کرد؟ در این صورت با خطای زیر مواجه می‌شویم:

برای جلوگیری از نشت حافظه، در راه‌حل خود از تابع پاکسازی useEffect همراه با شیء داخلی AbortController استفاده می‌کنیم:

1import React, { useState, useEffect } from "react";
2const useFetch = (url, options) => {
3  const [response, setResponse] = useState(null)
4  const [error, setError] = useState(null);
5  const [loading, setLoading] = useState(false);
6useEffect(() => {
7    const abortController = new AbortController();
8    const signal = abortController.signal;
9    const doFetch = async () => {
10      setLoading(true);
11      try {
12        const res = await fetch(url, options);
13        const json = await res.json();
14        if (!signal.aborted) {
15          setResponse(json);
16        }
17      } catch (e) {
18        if (!signal.aborted) {
19          setError(e);
20        }
21      } finally {
22        if (!signal.aborted) {
23          setLoading(false);
24        }
25      }
26    };
27    doFetch();
28    return () => {
29      abortController.abort();
30    };
31  }, []);
32  return { response, error, loading };
33};
34export default useFetch;

کاربرد

ما از قلاب سفارشی خود دقیقاً به همان روشی که از قلاب‌های دیگر استفاده می‌کنیم، بهره خواهیم گرفت. به خاطر داشته باشید که این قلاب به یک URL به عنوان آرگومان نخست نیاز دارد و در صورت نیاز می‌توانید به همراه گزینه‌ها آن را ارائه دهید:

1import React from "react";
2import ReactDOM from "react-dom";
3import useFetch from "./useFetch";
4function App() {
5  const { response, loading, error } = useFetch(
6    "https://jsonplaceholder.typicode.com/todos/1"
7  );
8  return (
9    <div className="App">
10      <h1>useFetch Usage</h1>
11      {loading && <p>Loading...</p>}
12      {error && <p>Something went wrong...</p>}
13      {response && <p>{response.title}</p>}
14    </div>
15  );
16}
17const rootElement = document.getElementById("root");
18ReactDOM.render(<App />, rootElement);

روش‌های بهبود قلاب سفارشی

در یک پروژه واقعی می‌توان در زمان واکشی کردن داده‌ها کارهای دیگری نیز انجام داد. قلاب ما می‌تواند با پیاده‌سازی قابلیت‌های زیر بهبود یابد:

  • کش کردن – پیش از واکشی کردن می‌توان در کش مورد استفاده، بررسی کرد که آیا داده‌ها از قبل واکشی شده‌اند و آیا نیاز به واکشی مجدد وجود دارد یا نه.
  • لاگ کردن خطا – اگر خطایی وجود داشته باشد باید آن را به اپلیکیشن سرویس یا شخص ثالث ارسال کنیم تا توسعه‌دهندگان از آن اطلاع یابند.
  • تعلیق ری‌اکت – کامپوننت <Suspense> امکان می‌دهد که منتظر شویم تا کدی بارگذاری شود و یک حالت بارگذاری را به صورت اعلانی در زمان انتظار برای بارگذاری داشته باشیم. این امکانی عالی است، اما از آنجا که هنوز در مرحله آزمایشی است، استفاده از آن هنوز توصیه نمی‌شود.
  • Effects – می‌تواند یک اکشن را در زمان پایان یافتن یا دریافت یک خطا به یک store مانند ریداکس ارسال کند.

سخن پایانی

کتابخانه‌های زیادی برای اجرای کاری که ما در این مقاله انجام دادیم وجود دارند. همچنان که مشاهده کردید، ایجاد یک قلاب سفارشی useFetch کاری واقعاً آسان است. دانستن شیوه ساخت قلاب‌های سفارشی موجب می‌شود که کنترل کاملی روی موارد نیاز داشته باشیم و به علاوه پروژه خود را از وابستگی به کتابخانه‌های دیگر برهانیم.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۲ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *