useEffect چیست؟

در ری اکت، هوک useEffect ابزاری مفید برای مدیریت اثرات جانبی (Side Effects) در کامپوننت‌های تابعی است.

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

  • دریافت داده از API یا سرور
  • تغییر عنوان صفحه مرورگر
  • تنظیم تایمر‌ها (مانند شمارش معکوس)
  • گوش دادن به رویدادهای کاربر مانند کلیک یا اسکرول

به‌بیان ساده، useEffect به شما امکان می‌دهد تعریف کنید که "پس از رندر شدن کامپوننت، چه عملیاتی باید انجام شود."

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

useEffect یک تابع در ری‌اکت است که دو آرگومان دریافت می‌کند:

useEffect(<function>, <dependency>)
  1. تابع اثر: تابعی که می‌خواهید پس از هر بار رندر شدن کامپوننت اجرا شود.
  2. آرایه وابستگی (اختیاری): آرایه‌ای از مقادیر که تعیین می‌کند تابع اثر چه زمانی دوباره اجرا شود. اگر این آرایه خالی باشد، تابع فقط یک‌بار پس از بارگذاری اولیه اجرا خواهد شد.
import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    console.log('Component Rendered');
  }); // بدون وابستگی

  return (
    <div>
      <p>Counter: {count}</p>
      <button onClick={() => setCount(count + 1)}>Add</button>
    </div>
  );
}

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

نقش آرایه وابستگی‌ها

آرایه وابستگی‌ها به ری‌اکت اطلاع می‌دهد که تابع اثر چه زمانی باید اجرا شود. این آرایه سه حالت اصلی دارد:

1. آرایه خالی ([])

در این حالت، تابع فقط یک‌بار، هنگام اولین رندر کامپوننت اجرا می‌شود.

useEffect(() => {
  fetch('https://fakestoreapi.com/products')
    .then(response => response.json())
    .then(data => setData(data));
}, []); // فقط یک‌بار هنگام بارگذاری

2. آرایه با مقادیر وابسته

اگر داخل آرایه مقادیری مثل count قرار دهید، تابع هر بار که آن مقدار تغییر کند اجرا خواهد شد.

useEffect(() => {
  document.title = `شما ${count} بار کلیک کردید`;
}, [count]);

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

useEffect(() => {
  setCount(count + 1); // خطرناک!
}, [count]);

3. بدون آرایه وابستگی

در این حالت، تابع با هر رندر کامپوننت (حتی بدون تغییر خاص) اجرا می‌شود.

useEffect(() => {
  console.log('این تابع با هر بار رندر اجرا می شود');
});

تمیزکاری (Cleanup)

بعضی وقت‌ها نیاز دارید بعد از اجرای useEffect یک کار را تمیز کنید، مثل متوقف کردن تایمر یا حذف شنونده رویداد. برای این کار، می‌توانید یک تابع تمیزکاری (Cleanup Function) از useEffect برگردانید.

useEffect(() => {
  const timer = setInterval(() => {
    console.log('تیک');
  }, 1000);

  return () => clearInterval(timer); // تابع تمیزکاری
}, []); // فقط یک بار اجرا می‌شود

تایمر هر ثانیه یک بار اجرا می‌شود، اما زمانی که کامپوننت از صفحه حذف شود، تابع تمیزکاری فعال شده و تایمر متوقف می‌شود. این روش مانع از باقی ماندن تایمرهای غیرضروری در حافظه شده و از نشتی حافظه (Memory Leak) جلوگیری می‌کند.

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

useEffect(() => {
  const handleClick = () => console.log('کلیک شد');
  window.addEventListener('click', handleClick);

  return () => window.removeEventListener('click', handleClick);
}, []); // فقط یک بار اجرا می‌شود

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

خلاصه درس

در این بخش یاد گرفتید که:

  • useEffect برای مدیریت اثرات جانبی (Side Effects) بعد از رندر کامپوننت استفاده می‌شود.
  • آرایه وابستگی‌ها زمان اجرای useEffect را کنترل می‌کند:
    • []: فقط یک‌بار، هنگام بارگذاری کامپوننت.
    • [variable]: هر بار که مقدار متغیر تغییر کند.
    • بدون آرایه: با هر بار رندر کامپوننت.
  • تمیزکاری: برای آزاد کردن منابع و جلوگیری از مشکلات حافظه (Memory Leak) ضروری است.

تمرین


مشاهده پاسخ
توسعه دهندگان
نیما عراقی