فارسی

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

هوک‌های سفارشی: الگوهای منطق قابل استفاده مجدد در ری‌اکت

هوک‌های ری‌اکت با معرفی قابلیت‌های state و lifecycle به کامپوننت‌های تابعی، انقلابی در نحوه نوشتن کامپوننت‌های ری‌اکت ایجاد کردند. در میان مزایای فراوانی که ارائه می‌دهند، هوک‌های سفارشی به عنوان یک مکانیزم قدرتمند برای استخراج و استفاده مجدد از منطق در چندین کامپوننت برجسته هستند. این پست وبلاگ به طور عمیق به دنیای هوک‌های سفارشی می‌پردازد و مزایا، نحوه ایجاد و استفاده از آن‌ها را با مثال‌های عملی بررسی می‌کند.

هوک‌های سفارشی چه هستند؟

در اصل، یک هوک سفارشی یک تابع جاوا اسکریپت است که با کلمه "use" شروع می‌شود و می‌تواند هوک‌های دیگر را فراخوانی کند. آن‌ها به شما این امکان را می‌دهند که منطق کامپوننت را در توابع قابل استفاده مجدد استخراج کنید. این یک راه قدرتمند برای به اشتراک گذاشتن منطق دارای state، اثرات جانبی، یا سایر رفتارهای پیچیده بین کامپوننت‌ها بدون توسل به render props، کامپوننت‌های مرتبه بالاتر، یا الگوهای پیچیده دیگر است.

ویژگی‌های کلیدی هوک‌های سفارشی:

مزایای استفاده از هوک‌های سفارشی

هوک‌های سفارشی چندین مزیت قابل توجه در توسعه ری‌اکت ارائه می‌دهند:

ایجاد اولین هوک سفارشی شما

بیایید ایجاد یک هوک سفارشی را با یک مثال عملی نشان دهیم: یک هوک که اندازه پنجره را ردیابی می‌کند.

مثال: useWindowSize

این هوک عرض و ارتفاع فعلی پنجره مرورگر را برمی‌گرداند. همچنین این مقادیر را هنگام تغییر اندازه پنجره به‌روزرسانی می‌کند.

import { useState, useEffect } from 'react';

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    window.addEventListener('resize', handleResize);

    // حذف شنونده رویداد هنگام پاک‌سازی
    return () => window.removeEventListener('resize', handleResize);
  }, []); // آرایه خالی تضمین می‌کند که effect فقط هنگام mount شدن اجرا شود

  return windowSize;
}

export default useWindowSize;

توضیح:

  1. وارد کردن هوک‌های لازم: ما useState و useEffect را از ری‌اکت وارد می‌کنیم.
  2. تعریف هوک: ما یک تابع به نام useWindowSize ایجاد می‌کنیم که از قاعده نام‌گذاری پیروی می‌کند.
  3. مقداردهی اولیه State: ما از useState برای مقداردهی اولیه state windowSize با عرض و ارتفاع اولیه پنجره استفاده می‌کنیم.
  4. راه‌اندازی شنونده رویداد: ما از useEffect برای افزودن یک شنونده رویداد resize به پنجره استفاده می‌کنیم. هنگامی که اندازه پنجره تغییر می‌کند، تابع handleResize state windowSize را به‌روزرسانی می‌کند.
  5. پاک‌سازی: ما یک تابع پاک‌سازی از useEffect برمی‌گردانیم تا شنونده رویداد را هنگام unmount شدن کامپوننت حذف کنیم. این کار از نشت حافظه جلوگیری می‌کند.
  6. مقادیر بازگشتی: هوک، شیء windowSize را که حاوی عرض و ارتفاع فعلی پنجره است، برمی‌گرداند.

استفاده از هوک سفارشی در یک کامپوننت

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

import React from 'react';
import useWindowSize from './useWindowSize';

function MyComponent() {
  const { width, height } = useWindowSize();

  return (
    

عرض پنجره: {width}px

ارتفاع پنجره: {height}px

); } export default MyComponent;

توضیح:

  1. وارد کردن هوک: ما هوک سفارشی useWindowSize را وارد می‌کنیم.
  2. فراخوانی هوک: ما هوک useWindowSize را درون کامپوننت فراخوانی می‌کنیم.
  3. دسترسی به مقادیر: ما شیء بازگشتی را destructure می‌کنیم تا مقادیر width و height را بدست آوریم.
  4. رندر کردن مقادیر: ما مقادیر عرض و ارتفاع را در UI کامپوننت رندر می‌کنیم.

هر کامپوننتی که از useWindowSize استفاده کند، با تغییر اندازه پنجره به طور خودکار به‌روزرسانی می‌شود.

مثال‌های پیچیده‌تر

بیایید چند مورد استفاده پیشرفته‌تر برای هوک‌های سفارشی را بررسی کنیم.

مثال: useLocalStorage

این هوک به شما اجازه می‌دهد تا به راحتی داده‌ها را از حافظه محلی (local storage) ذخیره و بازیابی کنید.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // State برای ذخیره مقدار ما
  // ارسال مقدار اولیه به useState تا منطق فقط یک بار اجرا شود
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // دریافت از حافظه محلی با کلید
      const item = window.localStorage.getItem(key);
      // تجزیه json ذخیره شده یا در صورت عدم وجود، بازگرداندن initialValue
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // در صورت خطا نیز initialValue را بازگردان
      console.log(error);
      return initialValue;
    }
  });

  // بازگرداندن یک نسخه بسته‌بندی شده از تابع setter هوک useState که ...
  // ... مقدار جدید را در localStorage پایدار می‌کند.
  const setValue = (value) => {
    try {
      // اجازه می‌دهد مقدار یک تابع باشد تا API مشابهی با useState داشته باشیم
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // ذخیره در حافظه محلی
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // ذخیره state
      setStoredValue(valueToStore);
    } catch (error) {
      // یک پیاده‌سازی پیشرفته‌تر، مورد خطا را مدیریت می‌کند
      console.log(error);
    }
  };

  useEffect(() => {
    try {
      const item = window.localStorage.getItem(key);
      setStoredValue(item ? JSON.parse(item) : initialValue);
    } catch (error) {
      console.log(error);
    }
  }, [key, initialValue]);

  return [storedValue, setValue];
}

export default useLocalStorage;

نحوه استفاده:

import React from 'react';
import useLocalStorage from './useLocalStorage';

function MyComponent() {
  const [name, setName] = useLocalStorage('name', 'Guest');

  return (
    

سلام، {name}!

setName(e.target.value)} />
); } export default MyComponent;

مثال: useFetch

این هوک منطق واکشی داده از یک API را کپسوله می‌کند.

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`خطای HTTP! وضعیت: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (error) {
        setError(error);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

نحوه استفاده:

import React from 'react';
import useFetch from './useFetch';

function MyComponent() {
  const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');

  if (loading) return 

در حال بارگذاری...

; if (error) return

خطا: {error.message}

; return (

عنوان: {data.title}

تکمیل شده: {data.completed ? 'بله' : 'خیر'}

); } export default MyComponent;

بهترین شیوه‌ها برای هوک‌های سفارشی

برای اطمینان از اینکه هوک‌های سفارشی شما مؤثر و قابل نگهداری هستند، این بهترین شیوه‌ها را دنبال کنید:

اشتباهات رایج که باید از آنها اجتناب کرد

الگوهای پیشرفته

ترکیب هوک‌های سفارشی

هوک‌های سفارشی را می‌توان با هم ترکیب کرد تا منطق پیچیده‌تری ایجاد شود. به عنوان مثال، می‌توانید یک هوک useLocalStorage را با یک هوک useFetch ترکیب کنید تا داده‌های واکشی شده را به طور خودکار در حافظه محلی ذخیره کنید.

اشتراک‌گذاری منطق بین هوک‌ها

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

استفاده از Context با هوک‌های سفارشی

هوک‌های سفارشی را می‌توان در ترکیب با React Context برای دسترسی و به‌روزرسانی state سراسری استفاده کرد. این به شما امکان می‌دهد کامپوننت‌های قابل استفاده مجددی ایجاد کنید که از state سراسری برنامه آگاه هستند و می‌توانند با آن تعامل داشته باشند.

مثال‌های دنیای واقعی

در اینجا چند نمونه از نحوه استفاده از هوک‌های سفارشی در برنامه‌های دنیای واقعی آورده شده است:

مثال: هوک useGeolocation برای برنامه‌های چندفرهنگی مانند نقشه‌برداری یا خدمات تحویل

import { useState, useEffect } from 'react';

function useGeolocation() {
  const [location, setLocation] = useState({
    latitude: null,
    longitude: null,
    error: null,
  });

  useEffect(() => {
    if (!navigator.geolocation) {
      setLocation({
        latitude: null,
        longitude: null,
        error: 'موقعیت یابی جغرافیایی توسط این مرورگر پشتیبانی نمی‌شود.',
      });
      return;
    }

    const watchId = navigator.geolocation.watchPosition(
      (position) => {
        setLocation({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          error: null,
        });
      },
      (error) => {
        setLocation({
          latitude: null,
          longitude: null,
          error: error.message,
        });
      }
    );

    return () => navigator.geolocation.clearWatch(watchId);
  }, []);

  return location;
}

export default useGeolocation;

نتیجه‌گیری

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

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

به یاد داشته باشید که از بهترین شیوه‌ها پیروی کنید، از اشتباهات رایج اجتناب کنید و الگوهای پیشرفته را برای بهره‌برداری حداکثری از هوک‌های سفارشی کاوش کنید. با تمرین و تجربه، شما به یک استاد هوک‌های سفارشی و یک توسعه‌دهنده ری‌اکت مؤثرتر تبدیل خواهید شد.