فارسی

قلاب React useEvent را بررسی کنید، ابزاری قدرتمند برای ایجاد مراجع پایدار کنترل کننده رویداد در برنامه های React پویا، بهبود عملکرد و جلوگیری از رندر مجدد غیر ضروری.

React useEvent: دستیابی به مراجع پایدار کنترل کننده رویداد

توسعه دهندگان React اغلب هنگام کار با کنترل کننده های رویداد، به ویژه در سناریوهایی که شامل اجزای پویا و Closure ها هستند، با چالش هایی روبرو می شوند. قلاب useEvent، یک افزودنی نسبتاً جدید به اکوسیستم React، یک راه حل ظریف برای این مسائل ارائه می دهد و توسعه دهندگان را قادر می سازد مراجع پایدار کنترل کننده رویداد را ایجاد کنند که باعث رندر مجدد غیر ضروری نمی شود.

درک مشکل: ناپایداری کنترل کننده های رویداد

در React، اجزا هنگام تغییر props یا state خود، دوباره رندر می شوند. هنگامی که یک تابع کنترل کننده رویداد به عنوان یک prop ارسال می شود، یک نمونه تابع جدید اغلب در هر رندر از کامپوننت والد ایجاد می شود. این نمونه تابع جدید، حتی اگر منطق یکسانی داشته باشد، توسط React متفاوت در نظر گرفته می شود و منجر به رندر مجدد کامپوننت فرزند می شود که آن را دریافت می کند.

این مثال ساده را در نظر بگیرید:


import React, { useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    console.log('Clicked from Parent:', count);
    setCount(count + 1);
  };

  return (
    

Count: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent rendered'); return ; } export default ParentComponent;

در این مثال، handleClick در هر رندر ParentComponent دوباره ایجاد می شود. حتی اگر ChildComponent ممکن است بهینه شده باشد (به عنوان مثال، با استفاده از React.memo)، همچنان دوباره رندر می شود زیرا prop onClick تغییر کرده است. این می تواند منجر به مشکلات عملکرد شود، به ویژه در برنامه های پیچیده.

معرفی useEvent: راه حل

قلاب useEvent این مشکل را با ارائه یک مرجع پایدار به تابع کنترل کننده رویداد حل می کند. این قلاب به طور موثر کنترل کننده رویداد را از چرخه رندر مجدد کامپوننت والد خود جدا می کند.

در حالی که useEvent یک قلاب داخلی React نیست (از React 18)، می توان آن را به راحتی به عنوان یک قلاب سفارشی پیاده سازی کرد یا در برخی از فریم ورک ها و کتابخانه ها به عنوان بخشی از مجموعه ابزار آنها ارائه می شود. در اینجا یک پیاده سازی رایج وجود دارد:


import { useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // UseLayoutEffect is crucial here for synchronous updates
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // The dependency array is intentionally empty, ensuring stability
  ) as T;
}

export default useEvent;

توضیحات:

استفاده از useEvent در عمل

اکنون، بیایید مثال قبلی را با استفاده از useEvent بازسازی کنیم:


import React, { useState, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // UseLayoutEffect is crucial here for synchronous updates
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // The dependency array is intentionally empty, ensuring stability
  ) as T;
}

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useEvent(() => {
    console.log('Clicked from Parent:', count);
    setCount(count + 1);
  });

  return (
    

Count: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent rendered'); return ; } export default ParentComponent;

با پیچیدن handleClick با useEvent، اطمینان حاصل می کنیم که ChildComponent همان مرجع تابع را در رندرهای ParentComponent دریافت می کند، حتی زمانی که state count تغییر می کند. این از رندر مجدد غیر ضروری ChildComponent جلوگیری می کند.

مزایای استفاده از useEvent

موارد استفاده برای useEvent

جایگزین ها و ملاحظات

در حالی که useEvent ابزاری قدرتمند است، رویکردهای جایگزین و ملاحظاتی وجود دارد که باید در نظر داشت:

ملاحظات بین المللی سازی و دسترسی

هنگام توسعه برنامه های React برای مخاطبان جهانی، توجه به بین المللی سازی (i18n) و دسترسی (a11y) بسیار مهم است. useEvent خود مستقیماً بر i18n یا a11y تأثیر نمی گذارد، اما می تواند به طور غیرمستقیم عملکرد اجزایی را که محتوای بومی سازی شده یا ویژگی های دسترسی را مدیریت می کنند، بهبود بخشد.

به عنوان مثال، اگر یک کامپوننت متن بومی سازی شده را نمایش می دهد یا از ویژگی های ARIA بر اساس زبان فعلی استفاده می کند، اطمینان از اینکه کنترل کننده های رویداد در آن کامپوننت پایدار هستند می تواند از رندر مجدد غیر ضروری هنگام تغییر زبان جلوگیری کند.

مثال: useEvent با بومی سازی


import React, { useState, useContext, createContext, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // UseLayoutEffect is crucial here for synchronous updates
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // The dependency array is intentionally empty, ensuring stability
  ) as T;
}

const LanguageContext = createContext('en');

function LocalizedButton() {
  const language = useContext(LanguageContext);
  const [text, setText] = useState(getLocalizedText(language));

  const handleClick = useEvent(() => {
    console.log('Button clicked in', language);
    // Perform some action based on the language
  });

  function getLocalizedText(lang) {
      switch (lang) {
        case 'en':
          return 'Click me';
        case 'fr':
          return 'Cliquez ici';
        case 'es':
          return 'Haz clic aquí';
        default:
          return 'Click me';
      }
    }

    //Simulate language change
    React.useEffect(()=>{{
        setTimeout(()=>{{
            setText(getLocalizedText(language === 'en' ? 'fr' : 'en'))
        }}, 2000)
    }}, [language])

  return ;
}

function App() {
  const [language, setLanguage] = useState('en');

  const toggleLanguage = useCallback(() => {
    setLanguage(language === 'en' ? 'fr' : 'en');
  }, [language]);

  return (
    
      
); } export default App;

در این مثال، کامپوننت LocalizedButton متن را بر اساس زبان فعلی نمایش می دهد. با استفاده از useEvent برای کنترل کننده handleClick، اطمینان حاصل می کنیم که دکمه هنگام تغییر زبان به طور غیر ضروری دوباره رندر نمی شود و عملکرد و تجربه کاربر را بهبود می بخشد.

نتیجه

قلاب useEvent ابزاری ارزشمند برای توسعه دهندگان React است که به دنبال بهینه سازی عملکرد و ساده سازی منطق کامپوننت هستند. با ارائه مراجع پایدار کنترل کننده رویداد، از رندر مجدد غیر ضروری جلوگیری می کند، خوانایی کد را بهبود می بخشد و کارایی کلی برنامه های React را افزایش می دهد. در حالی که این یک قلاب داخلی React نیست، پیاده سازی ساده و مزایای قابل توجه آن، آن را به یک افزودنی ارزشمند برای جعبه ابزار هر توسعه دهنده React تبدیل می کند.

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