هوک های سفارشی (Custom Hooks)
هوک های سفارشی در ری اکت یعنی تابع هایی که خودت می سازی تا منطق تکراری را یک جا جمع کنی و دوباره استفاده کنی. مثل اینکه برای مشق ریاضی یک فرمول خلاصه مخصوص خودت بسازی و هر بار از همان فرمول استفاده کنی.
هوک های سفارشی در ری اکت چیست؟
هوک (Hook) تابع کمکی ری اکت است که به کامپوننت قدرت اضافه می کند. هوک های سفارشی در ری اکت همان هوک هایی هستند که خودت می نویسی، نه آن هایی که خود ری اکت داده است مثل useState.
طبق منبع، وقتی چند کامپوننت از یک منطق مشترک استفاده می کنند، بهتر است آن منطق را در یک هوک سفارشی قرار بدهیم. نام همه هوک های سفارشی باید با use شروع شود، مثل useFetch.
نکته: نام فایل هم معمولاً با use شروع می شود و با .js تمام می شود؛ مثلاً useFetch.js در همان پوشه کامپوننت اصلی.
مثال بدون استفاده از هوک سفارشی
در این مثال منبع، مستقیم داخل کامپوننت Home داده را از یک آدرس می گیریم و نشان می دهیم. سرویس JSONPlaceholder فقط داده جعلی برای تمرین API می دهد و برای تست خیلی مناسب است.
در کد زیر از useState برای نگه داشتن data و از useEffect برای fetch کردن داده استفاده شده است. منطق fetch فعلاً داخل خود کامپوننت است.
مثال: گرفتن داده بدون هوک سفارشی
import { useState, useEffect } from "react";
import { createRoot } from "react-dom/client";
const Home = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => {
return res.json();
})
.then((data) => {
setData(data);
});
}, []);
return (
<>
{data &&
data.map((item) => {
return (
<p key={item.id}>
{item.title}
</p>
);
})}
</>
);
};
createRoot(document.getElementById("root")).render(
<Home />
);
منبع توضیح می دهد که همین منطق fetch ممکن است در چند کامپوننت دیگر هم لازم شود. اگر کپی کنیم، کد تکراری زیاد می شود و نگه داری سخت می شود. اینجا هوک های سفارشی در ری اکت وارد بازی می شوند.
نکته: سرویس JSONPlaceholder برای تمرین خیلی عالی است، چون داده تستی رایگان می دهد.
ساخت یک هوک سفارشی useFetch
در قدم بعد، منبع منطق fetch را به فایل جدا منتقل می کند. این فایل همان هوک سفارشی در ری اکت است و نامش useFetch.js می باشد. این هوک یک url می گیرد و داده آن را برمی گرداند.
داخل useFetch از useState و useEffect استفاده می شود، یعنی هوک های آماده را در دل یک هوک سفارشی ترکیب می کنیم. در نهایت، data را به صورت آرایه برمی گردانیم تا شبیه الگوی useState باشد.
مثال: تعریف هوک سفارشی useFetch
import { useState, useEffect } from "react";
const useFetch = (url) => {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((res) => {
return res.json();
})
.then((data) => {
setData(data);
});
}, [url]);
return [data];
};
export default useFetch;
این جا چند نکته مهم وجود دارد: آدرس ثابت حذف شده و جای آن پارامتر url آمده است. همچنین useEffect وابسته به url شده، پس هر وقت url عوض شود دوباره fetch انجام می شود.
برگرداندن [data] باعث می شود هنگام استفاده، مثل useState از destructuring استفاده کنیم. مثلاً بنویسیم const [data] = useFetch(url); و این خیلی خواناتر است.
استفاده از هوک سفارشی در کامپوننت
حالا نوبت این است که هوک useFetch را در یک کامپوننت واقعی استفاده کنیم. منبع دوباره کامپوننت Home را می سازد، اما این بار منطق fetch دیگر داخلش نیست.
فقط useFetch را صدا می زنیم و داده آماده را می گیریم. این یعنی کد تمیزتر، کوتاه تر و قابل استفاده مجدد در چند جای پروژه.
مثال: استفاده از هوک سفارشی در Home
import { createRoot } from "react-dom/client";
import useFetch from "./useFetch";
const Home = () => {
const [data] = useFetch("https://jsonplaceholder.typicode.com/todos");
return (
<>
{data &&
data.map((item) => {
return (
<p key={item.id}>
{item.title}
</p>
);
})}
</>
);
};
createRoot(document.getElementById("root")).render(
<Home />
);
حالا هر وقت یک آدرس دیگر خواستی کافی است همین هوک های سفارشی در ری اکت را دوباره استفاده کنی. فقط url را عوض می کنی و بقیه منطق همان است.
نکته: در فایل اصلی، useFetch درست مثل هر هوک دیگری استفاده می شود. تفاوتی با useEffect از نظر نحوه صدا زدن نمی بینی.
توضیح مثال هوک های سفارشی
منبع در پایان مثال را جمع بندی می کند. می گوید ما تمام منطق fetch را به useFetch منتقل کردیم و URL ثابت را به پارامتر url تبدیل کردیم. در نهایت data را برگرداندیم.
در main.jsx یا همان فایل اصلی، useFetch را ایمپورت کرده ایم و از آن استفاده می کنیم. اینجا همان جاست که آدرس واقعی را به هوک می دهیم. حالا این هوک را می توانیم در هر کامپوننت دیگری هم استفاده کنیم.
اگر قبلاً با useEffect برای fetch کار کرده ای، این الگو فقط یک قدم جلوتر است. می توانی برای مرور مفهوم وابستگی ها، صفحه هوک useEffect را هم نگاه کنی.
گام های ساخت هوک های سفارشی در ری اکت
- 1) منطق تکراری را در چند کامپوننت پیدا کن.
- 2) یک فایل جدید با نامی شبیه useSomething.js بساز.
- 3) داخل آن از هوک های معمولی مثل useState و useEffect استفاده کن.
- 4) ورودی ها را به صورت پارامتر بگیر، نه مقدار ثابت.
- 5) نتیجه را برگردان و در کامپوننت ها ایمپورت و استفاده کن.
اگر کل مبحث هوک ها برایت جالب است، بعد از این صفحه حتماً به بخش هوک useMemo هم سر بزن تا با بهینه سازی محاسبات سنگین آشنا شوی.
برای رجوع سریع، این صفحه را به عنوان مرجع «هوک های سفارشی در ری اکت» ذخیره کن. این عبارت را در سایت خودت هم می توانی به همین صفحه لینک بدهی: هوک های سفارشی در ری اکت.
جمع بندی سریع
- هوک های سفارشی در ری اکت منطق تکراری را قابل استفاده مجدد می کنند.
- نام همه هوک های سفارشی باید با use شروع شود.
- می توانی داخل هوک سفارشی از useState و useEffect استفاده کنی.
- هوک useFetch نمونه ای ساده برای گرفتن داده از هر URL است.
- با هوک های سفارشی، کد تمیزتر و نگه داری راحت تر می شود.