العربية

أطلق العنان لقوة المنطق القابل لإعادة الاستخدام في تطبيقات React الخاصة بك باستخدام الخطافات المخصصة. تعلم كيفية إنشائها والاستفادة منها لكتابة كود أنظف وأكثر قابلية للصيانة.

الخطافات المخصصة: أنماط منطقية قابلة لإعادة الاستخدام في React

أحدثت خطافات React ثورة في طريقة كتابتنا لمكونات React من خلال تقديم ميزات الحالة ودورة الحياة للمكونات الوظيفية. من بين الفوائد العديدة التي تقدمها، تبرز الخطافات المخصصة كآلية قوية لاستخلاص وإعادة استخدام المنطق عبر مكونات متعددة. ستتعمق هذه التدوينة في عالم الخطافات المخصصة، مستكشفة فوائدها وإنشائها واستخدامها مع أمثلة عملية.

ما هي الخطافات المخصصة؟

في جوهرها، الخطاف المخصص هو دالة JavaScript تبدأ بكلمة "use" ويمكنها استدعاء خطافات أخرى. تسمح لك باستخلاص منطق المكونات في دوال قابلة لإعادة الاستخدام. هذه طريقة قوية لمشاركة المنطق ذي الحالة، أو الآثار الجانبية، أو السلوكيات المعقدة الأخرى بين المكونات دون اللجوء إلى "render props" أو المكونات عالية الرتبة أو الأنماط المعقدة الأخرى.

الخصائص الرئيسية للخطافات المخصصة:

فوائد استخدام الخطافات المخصصة

تقدم الخطافات المخصصة العديد من المزايا الهامة في تطوير React:

إنشاء أول خطاف مخصص لك

دعنا نوضح إنشاء خطاف مخصص بمثال عملي: خطاف يتتبع حجم النافذة.

مثال: 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);
  }, []); // المصفوفة الفارغة تضمن تشغيل التأثير عند التحميل فقط

  return windowSize;
}

export default useWindowSize;

الشرح:

  1. استيراد الخطافات اللازمة: نستورد useState و useEffect من React.
  2. تعريف الخطاف: ننشئ دالة باسم useWindowSize، ملتزمين بقاعدة التسمية.
  3. تهيئة الحالة: نستخدم useState لتهيئة حالة windowSize بالعرض والارتفاع الأوليين للنافذة.
  4. إعداد مستمع الحدث: نستخدم useEffect لإضافة مستمع حدث "resize" إلى النافذة. عند تغيير حجم النافذة، تقوم دالة handleResize بتحديث حالة windowSize.
  5. التنظيف: نعيد دالة تنظيف من useEffect لإزالة مستمع الحدث عند إلغاء تحميل المكون. هذا يمنع تسرب الذاكرة.
  6. إرجاع القيم: يعيد الخطاف كائن windowSize، الذي يحتوي على العرض والارتفاع الحاليين للنافذة.

استخدام الخطاف المخصص في مكون

الآن بعد أن أنشأنا خطافنا المخصص، دعنا نرى كيفية استخدامه في مكون React.

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. الوصول إلى القيم: نقوم بتفكيك الكائن المعاد للحصول على قيم width و height.
  4. عرض القيم: نعرض قيم العرض والارتفاع في واجهة المستخدم للمكون.

أي مكون يستخدم useWindowSize سيتم تحديثه تلقائيًا عند تغيير حجم النافذة.

أمثلة أكثر تعقيدًا

دعنا نستكشف بعض حالات الاستخدام الأكثر تقدمًا للخطافات المخصصة.

مثال: useLocalStorage

يسمح لك هذا الخطاف بتخزين واسترداد البيانات بسهولة من التخزين المحلي (local storage).

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // حالة لتخزين قيمتنا
  // تمرير القيمة الأولية إلى useState بحيث يتم تنفيذ المنطق مرة واحدة فقط
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // الحصول على القيمة من التخزين المحلي بواسطة المفتاح
      const item = window.localStorage.getItem(key);
      // تحليل JSON المخزن أو إرجاع القيمة الأولية في حالة عدم وجوده
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // في حالة حدوث خطأ، قم أيضًا بإرجاع القيمة الأولية
      console.log(error);
      return initialValue;
    }
  });

  // إرجاع نسخة مغلفة من دالة setter الخاصة بـ useState والتي ...
  // ... تحتفظ بالقيمة الجديدة في localStorage.
  const setValue = (value) => {
    try {
      // السماح بأن تكون القيمة دالة حتى يكون لدينا نفس واجهة برمجة التطبيقات مثل useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // الحفظ في التخزين المحلي
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // حفظ الحالة
      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 error! status: ${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 للحفاظ على البيانات التي تم جلبها تلقائيًا في التخزين المحلي.

مشاركة المنطق بين الخطافات

إذا كانت هناك خطافات مخصصة متعددة تشترك في منطق مشترك، يمكنك استخلاص هذا المنطق في دالة مساعدة منفصلة وإعادة استخدامه في كلا الخطافين.

استخدام السياق مع الخطافات المخصصة

يمكن استخدام الخطافات المخصصة بالاقتران مع React Context للوصول إلى الحالة العامة وتحديثها. يتيح لك ذلك إنشاء مكونات قابلة لإعادة الاستخدام تكون على دراية بالحالة العامة للتطبيق ويمكنها التفاعل معها.

أمثلة من العالم الحقيقي

فيما يلي بعض الأمثلة على كيفية استخدام الخطافات المخصصة في تطبيقات العالم الحقيقي:

مثال: خطاف 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;

الخاتمة

الخطافات المخصصة هي أداة قوية لكتابة كود React أنظف وأكثر قابلية لإعادة الاستخدام والصيانة. من خلال تغليف المنطق المعقد في خطافات مخصصة، يمكنك تبسيط مكوناتك وتقليل تكرار الكود وتحسين الهيكل العام لتطبيقاتك. احتضن الخطافات المخصصة وأطلق العنان لإمكاناتها لبناء تطبيقات React أكثر قوة وقابلية للتوسع.

ابدأ بتحديد المناطق في قاعدة الكود الحالية الخاصة بك حيث يتم تكرار المنطق عبر مكونات متعددة. بعد ذلك، قم بإعادة هيكلة هذا المنطق في خطافات مخصصة. بمرور الوقت، ستبني مكتبة من الخطافات القابلة لإعادة الاستخدام التي ستسرع عملية التطوير وتحسن جودة الكود الخاص بك.

تذكر أن تتبع أفضل الممارسات، وتتجنب الأخطاء الشائعة، وتستكشف الأنماط المتقدمة لتحقيق أقصى استفادة من الخطافات المخصصة. مع الممارسة والخبرة، ستصبح محترفًا في استخدام الخطافات المخصصة ومطور React أكثر فعالية.