آموزش React: راهنمای کامل useEffect
عباس سپهوند
عباس سپهوند
  • 1402/02/21
  • 25 دقیقه
  • 0 نظر

آموزش React: راهنمای کامل useEffect

useEffect یکی از مفاهیم مهم و پایه ای React است که لازم است شما به عنوان یک توسعه دهنده ری اکت بر تمام جنبه های آن مسط شوید در این بخش از آموزش ری اکت، به بررسی کامل این مفهوم مهم می پردازیم

 useEffect تابعی است که شما می‌توانید آن را برای اجرای عملیاتی که باید به محض  بروزرسانی یک کامپوننت اجرا شود استفاده کنید. با استفاده از useEffect می‌توانید با مشخص کردن یک تابع و شرط‌هایی که باید برای اجرای آن برقرار باشند، کدی را که به وضعیت یک کامپوننت وابسته است اجرا کنید. به عنوان مثال، شما می‌توانید با استفاده از useEffect یک درخواست API را برای دریافت داده‌ها ارسال کنید و آن‌ها را در state کامپوننت ذخیره کنید. در این بخش از آموزش React به بررسی کامل این مفهوم مهم می پردازیم و تمامی جنبه های این مفهوم را بررسی می کنیم. جزئیات کامل این مفهوم را می توانید در دوره آموزش React بررسی کنید

البته، بهتر است با یک مثال ساده در ابتدا این مفهوم را بررسی کنیم. یک مثال ساده از استفاده از useEffect برای درک بهتر عملکرد آن می‌تواند به این شکل باشد:

 

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

 

در این مثال، یک state به نام count با مقدار اولیه ۰ تعریف شده است. در تابع useEffect، ما عنوان صفحه را به مقدار جدید count تنظیم می‌کنیم. توجه کنید که تابع useEffect بدون مقدار دوم استفاده شده است. این به این معناست که کد مربوط به useEffect همیشه اجرا می‌شود، به عبارت دیگر، هر بار که مقدار count تغییر کند، تابع useEffect مجددا اجرا خواهد شد و عنوان صفحه بروزرسانی خواهد شد. با این مثال ساده می توانیم به جزئیات این مفهوم بپردازیم.

 

مفاهیم کلیدی useEffect

مفاهیم کلیدی و اساسی useEffect در React عبارتند از:

۱. اجرا شدن useEffect بعد از رندر شدن کامپوننت: تابع useEffect همیشه پس از اجرای کدی که مربوط به رندر کامپوننت است اجرا می‌شود. بنابراین، هر تغییری در وضعیت کامپوننت (state) منجر به رندر مجدد کامپوننت و اجرای دوباره‌ی تابع useEffect می‌شود. البته دقت کنید تعداد اجرای تابعی که در این هوک تعریف می شود قابل تنظیم است که در ادامه به این موضوع می پردازیم.

۲. تعریف یک تابع callback در useEffect: تابع callback تعریف شده در useEffect، کدی را اجرا می‌کند که وابسته به تغییراتی است که در state کامپوننت رخ می‌دهد. این تابع می‌تواند هرگونه عملیاتی را انجام دهد، از جمله درخواست‌های شبکه، تغییر DOM و ... .

۳. تعریف شرط‌هایی برای اجرای تابع callback: می‌توانید شرط‌هایی را برای اجرای تابع callback در useEffect تعریف کنید. در صورتی که شرط‌ها برقرار نباشند، تابع callback اجرا نخواهد شد. برای مثال، می‌توانید شرطی برای بروزرسانی state تعریف کنید تا تابع callback اجرا شود.

۴. بازگشت یک تابع cleanup: می‌توانید یک تابع cleanup در useEffect تعریف کنید تا کدی را که باید بعد از اجرای تابع callback انجام شود تعریف کنید. این تابع به صورت دلخواه است و می‌تواند هرگونه عملیاتی را انجام دهد، از جمله از بین بردن یک شبکه، حذف listener و ... .

 

استفاده از useEffect در API کال ها

استفاده از useEffect در asynchronous task ها به شما این امکان را می‌دهد که به راحتی از کدهایی که زمان زیادی برای اجرا نیاز دارند، مانند درخواست های شبکه و یا دسترسی به دیتابیس، استفاده کنید. برای این کار می‌توانید از تابع async و await در تابع callback استفاده کنید.

به عنوان مثال، فرض کنید یک درخواست شبکه از API در کامپوننتی وجود دارد که باید در هنگام نمایش آن، از API داده بگیریم و آن را به روز کنیم. با استفاده از useEffect می‌توانیم این کار را انجام دهیم. به صورت زیر:

 

import { useState, useEffect } from 'react';
import axios from 'axios';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const result = await axios.get('https://my-api.com/data');
      setData(result.data);
    }
    fetchData();
  }, []);

  return (
    <div>
      {data ? (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.title}</li>
          ))}
        </ul>
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
}

 

در این مثال، تابع fetchData با استفاده از async و await از API داده‌ها را دریافت می‌کند. سپس در تابع callback از useEffect، تابع fetchData را فراخوانی می‌کنیم. با استفاده از آرگومان دوم []، می‌توانیم اطمینان حاصل کنیم که این کد تنها در هنگام اولین بار لود شدن کامپوننت اجرا می‌شود و برای بروزرسانی‌های بعدی مجدداً اجرا نمی‌شود.

استفاده از useEffect در asynchronous task ها به شما این امکان را می‌دهد که با استفاده از تابع async و await، به صورت همزمان به کدهایی که زمان زیادی برای اجرا نیاز دارند، دسترسی پیدا کنید و در کل کدهای خود را بهبود بخشید.

 

استفاده از چند useEffect 

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

به عنوان مثال، فرض کنید یک کامپوننت داریم که از دو عملکرد استفاده می‌کند. یکی برای دریافت داده از API و دیگری برای اعمال افکت‌ها روی صفحه.

 

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function MyComponent() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      const result = await axios.get('https://my-api.com/data');
      setData(result.data);
      setLoading(false);
    }
    fetchData();
  }, []);

  useEffect(() => {
    if (!loading) {
      // اعمال افکت‌ها بر روی صفحه
    }
  }, [loading]);

  return (
    <div>
      {loading ? (
        <p>Loading...</p>
      ) : (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

 

در این مثال، ابتدا از useEffect برای دریافت داده از API استفاده کردیم. سپس با استفاده از useState، یک وضعیت برای نمایش پیام "Loading..." تعریف کردیم. در useEffect بعدی، از وضعیت loading برای اعمال افکت‌ها بر روی صفحه استفاده کردیم. با تغییر وضعیت loading در تابع fetchData، این useEffect مجدداً فراخوانی می‌شود و افکت‌های مربوط به صفحه را اعمال می‌کند.

به این ترتیب، با استفاده از چند useEffect، می‌توانید کد خود را به صورت سازمان‌دهی شده و منظم نگه دارید.

 

چه زمانی useEffect اجرا می شود؟

useEffect در کامپوننت هنگامی اجرا می‌شود که کامپوننت رندر می‌شود یا وضعیت آن تغییر می‌کند. برای دقیق‌تر بیان کردن زمانی که useEffect اجرا می‌شود، می‌توانیم از مفهوم "مرحله عمر کامپوننت" یا "وضعیت" استفاده کنیم.

  1. رندر اولیه کامپوننت: در این مرحله، useEffect بلافاصله پس از رندر اولیه کامپوننت اجرا می‌شود.

  2. به‌روزرسانی کامپوننت به علت تغییرات در ویژگی‌های ورودی (props): اگر ویژگی‌های ورودی (props) کامپوننت به روزرسانی شوند، useEffect پس از اعمال تغییرات و قبل از رندر مجدد کامپوننت اجرا می‌شود.

  3. به‌روزرسانی کامپوننت به علت تغییر وضعیت (state) محلی: اگر وضعیت کامپوننت به دلیل تغییرات در محاسبات داخلی کامپوننت به‌روزرسانی شود، useEffect پس از اعمال تغییرات و قبل از رندر مجدد کامپوننت اجرا می‌شود.

  4. حذف کامپوننت: در این مرحله، useEffect به عنوان Cleanup Function برای حذف هرگونه منبع خارجی یا عملیات پاک‌سازی قبل از حذف کامپوننت اجرا می‌شود.

با توجه به موارد فوق، می‌توانیم برای هر کدام از حالات زیر، useEffect را با یک شرط اجرا کنیم:

 

useEffect(() => {
  // code to be executed when the component is mounted (on initial render)
}, [])

useEffect(() => {
  // code to be executed when the component is updated due to changes in props
}, [prop1, prop2])

useEffect(() => {
  // code to be executed when the component is updated due to changes in local state
}, [localState1, localState2])

useEffect(() => {
  // code to be executed before the component is unmounted
  return () => {
   }
}

در واقع می توان گفت در 4 سناریو مختلف useEffect اجرا می شود:

  • بارگیری اولین بار: useEffect با اجرای کامپوننت برای اولین بار اجرا می‌شود. به عبارت دیگر، useEffect به صورت پیش‌فرض هنگامی که کامپوننت لود می‌شود اجرا می‌شود.
  • بروزرسانی کامپوننت: هر بار که ویژگی‌های کامپوننت تغییر می‌کند، useEffect دوباره اجرا می‌شود. به عنوان مثال، هر بار که مقداری در ویژگی‌های ورودی کامپوننت تغییر می‌کند، useEffect دوباره اجرا می‌شود.
  • بروزرسانی ویژگی‌های خاص: می‌توانید useEffect را برای بروزرسانی ویژگی‌های خاص کامپوننت استفاده کنید. برای این کار، می‌توانید یک لیست از ویژگی‌ها را به useEffect ارائه دهید. به عنوان مثال، اگر می‌خواهید useEffect فقط زمانی اجرا شود که مقداری از ویژگی‌های خاص تغییر کرده باشد، می‌توانید این ویژگی‌ها را به عنوان ورودی به useEffect اضافه کنید.
  • ترک کامپوننت: زمانی که کامپوننت از صفحه حذف می‌شود، useEffect با تابع cleanup مرتبط خود اجرا می‌شود. به عبارت دیگر، زمانی که کاربر از صفحه خارج می‌شود، تمامی منابع مصرفی کامپوننت (مانند شبکه، سیستم فایل، حافظه و ...) آزاد شده و cleanup function اجرا می‌شود.

 

تعیین زمان اجرا تابع با استفاده از Dependency Array

همانطور که گفته شد Dependency array در useEffect شامل مقادیری است که تغییر آنها باعث اجرای دوباره callback function در useEffect می‌شود. برخی از انواع معمول dependency array عبارتند از:

1- Dependency array خالی: اگر dependency array خالی باشد، callback function در useEffect فقط یکبار اجرا می‌شود و در صورت تغییر هیچ dependency ای، دوباره اجرا نمی‌شود.

مثال:

 

useEffect(() => {
  console.log("Component mounted");
}, []);

 

2- Dependency array با وجود یک مقدار: اگر مقداری در dependency array وجود داشته باشد، callback function در useEffect زمانی اجرا می‌شود که آن مقدار تغییر کند.

مثال:

 

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

useEffect(() => {
  console.log(`Count changed to ${count}`);
}, [count]);

 

3- Dependency array با وجود چند مقدار: اگر چندین مقدار در dependency array وجود داشته باشد، callback function در useEffect زمانی اجرا می‌شود که هر یک از آنها تغییر کند.

مثال:

 

const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");

useEffect(() => {
  console.log(`Full name changed to ${firstName} ${lastName}`);
}, [firstName, lastName]);

 

4- Dependency array با عدم وجود آن: اگر هیچ dependency arrayی در useEffect وجود نداشته باشد، callback function هر بار که هر کدام از متغیرهای state در component تغییر کند، دوباره اجرا می‌شود.

مثال:

 

const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");

useEffect(() => {
  console.log(`Full name changed to ${firstName} ${lastName}`);
});

// برای تغییر stateها مقدار زیر را به کار ببرید
// setFirstName("John");
// setLastName("Doe");

 

5- Dependency array با استفاده از مقداری به نام previous state: می‌توانید از مقداری به نام previous state استفاده کنید تا بتوانید تغییرات مقدار state را مقایسه کنید و در صورت تغییرات مورد نیاز، callback function را اجرا کنید.

مثال:

 

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

useEffect(() => {
  console.log(`Count changed from ${prevState.count} to ${count}`);
}, [count]);

 

به طور کلی dependency array می‌تواند ترکیبی از انواع مختلفی باشد که بسته به نیاز پروژه و متغیرهایی که در component استفاده می‌شوند، تنظیم می‌شوند. در نهایت، تنظیم درست dependency array در useEffect می‌تواند به بهینه‌تر کردن عملکرد component و کاهش تعداد re-renderهای غیر ضروری در React کمک کند.

 

Cleanup Function چیست و چه کاربردی دارد؟

Cleanup function یک تابع است که در useEffect تعریف می شود و وظیفه آن پاکسازی و رفع اثرات کنونی کامپوننت است. این تابع هنگامی فراخوانی می شود که کامپوننت غیرفعال شود یا به روزرسانی شود و یا کامپوننت از DOM حذف شود.

مثال:

 

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    console.log('Component did mount or update');
    
    // cleanup function
    return () => {
      console.log('Component will unmount or update');
    }
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

 

در این مثال، useEffect یک callback function دریافت می کند و هر بار که کامپوننت mount یا update می شود، این callback function فراخوانی می شود. همچنین، useEffect یک تابع cleanup دارد که هر بار که کامپوننت unmount یا update می شود، این تابع فراخوانی می شود و اثرات کامپوننت را پاکسازی می کند.

 

چه زمانی از useEffect استفاده نکنیم؟

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

  • در صورتی که قرار نیست در حین بارگیری صفحه داده‌های دیگری از سرور دریافت کنیم، مانند صفحه‌های استاتیک، نیازی به استفاده از useEffect نیست.

  • در صورتی که نیازی به اجرای یک کد در هنگام بروزرسانی UI نباشد، مثلا اگر اجزای UI شما به صورت دائمی در حال نمایش داده شدن هستند، نیازی به استفاده از useEffect نیست.

  • در صورتی که اجرای کدی که درون useEffect قرار دارد، زمان زیادی نمی‌برد و از منابع سنگینی استفاده نمی‌کند، می‌توان آن را در قسمت مربوطه، مثلا در هنگام رندر کامپوننت، اجرا کرد.

  • در صورتی که کدی که درون useEffect قرار دارد، در هر بار رندر کامپوننت، نیازی به اجرا ندارد، بلکه فقط در زمان بارگیری صفحه اجرا شود، می‌توان از useEffect استفاده کرد، اما حتماً باید dependency array آن را خالی گذاشت تا فقط در اولین بار بارگیری صفحه اجرا شود.

به طور کلی، استفاده از useEffect باید با توجه به نیازهای پروژه و در مواردی که واقعاً نیاز به اجرای کد در هنگام بروزرسانی UI وجود دارد، صورت گیرد.

 

خلاصه

useEffect یک Hook در React است که به شما امکان می دهد به راحتی با چرخه عمر کامپوننت ها در React کار کنید. این Hook مجموعه ای از توابع را در اختیار شما قرار می دهد تا بتوانید با تغییرات مرتبط با اجرای کامپوننت خود، کد خود را به روز کنید.

استفاده از useEffect در کامپوننت ها به شما این امکان را می دهد که به راحتی با محتوایی که به سایت یا برنامه شما بارگذاری شده است، کار کنید. همچنین می توانید با استفاده از useEffect بر روی داده هایی که برای کاربر باید به روز شوند، کنترل داشته باشید.

در کل، استفاده از useEffect به شما این امکان را می دهد که با تغییرات مرتبط با اجرای کامپوننت خود، کد خود را به روز کنید و بتوانید به راحتی با محتوایی که به سایت یا برنامه شما بارگذاری شده است، کار کنید.

برای جزئیات بیشتر این مفهوم می توانید دوره جامع آموزش React را بررسی و در این دوره شرکت کنید

دیدگاه

برای ارسال دیدگاه های خود ابتدا وارد شوید یا ثبت نام کنید

ورود یا ثبت نام
عباس سپهوند
عباس سپهوند

برنامه نویس و توسعه دهنده نرم افزار

مشاهده پروفایل
5 مقاله اخیر

آموزش React: راهنمای کامل useCallback

عباس سپهوند
زمان مطالعه: 40

آموزش React: راهنمای کامل useEffect

عباس سپهوند
زمان مطالعه: 25

آموزش React: راهنمای کامل Ref ها در React

عباس سپهوند
زمان مطالعه: 15
مشاهده همه مقالات