الگوریتم اول

لطفا صبر کنید...

مدیریت اثرات جانبی با useEffect در React

در برنامه‌های React، برخی عملیات مانند درخواست‌های API، کار با localStorage، تغییر عنوان صفحه، تایمرها و تعامل با DOM را نمی‌توان مستقیماً در بدنه کامپوننت انجام داد. برای مدیریت این اثرات جانبی (Side Effects) از هوک useEffect استفاده می‌کنیم.

 

۱. useEffect چیست و چرا مهم است؟

useEffect یک هوک React است که اجازه می‌دهد عملیات جانبی را در کامپوننت‌های فانکشنی مدیریت کنیم. این هوک جایگزین متدهای componentDidMount، componentDidUpdate و componentWillUnmount در کامپوننت‌های کلاسی شده است.

ساختار کلی useEffect

useEffect(() => {
  // کد مربوط به اثر جانبی
  return () => {
    // کد پاک‌سازی (اختیاری)
  };
}, [dependencies]);

 

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


۲. اجرای useEffect در هر رندر

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

مثال: نمایش پیام در Console در هر رندر

import React, { useState, useEffect } from "react";
const Counter = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log("کامپوننت رندر شد!");
  });
  return (
    <div>
      <h1>عدد: {count}</h1>
      <button onClick={() => setCount(count + 1)}>افزایش</button>
    </div>
  );
};
export default Counter;

✅ در این مثال، console.log در هر بار تغییر count اجرا می‌شود.
✅ از آنجا که useEffect بدون آرایه وابستگی است، در هر رندر اجرا خواهد شد.

 

۳. اجرای useEffect فقط هنگام mount (بارگذاری اولیه)

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

مثال: درخواست API فقط هنگام لود شدن

import React, { useState, useEffect } from "react";
const Users = () => {
  const [users, setUsers] = useState([]);
  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(data => setUsers(data));
  }, []); // آرایه خالی یعنی فقط یک‌بار اجرا شود.
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};
export default Users;

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

 

۴. اجرای useEffect هنگام تغییر مقدار خاص

می‌توان مشخص کرد که useEffect فقط هنگام تغییر مقدار خاصی اجرا شود.

مثال: اجرای useEffect فقط هنگام تغییر count

useEffect(() => {
  console.log(`مقدار count تغییر کرد: ${count}`);
}, [count]); // فقط وقتی count تغییر کند اجرا می‌شود.

 

اگر count تغییر کند، useEffect اجرا می‌شود.
✅ اگر مقدار دیگری (مثلاً یک ورودی متن) تغییر کند، useEffect اجرا نخواهد شد.

 

۵. پاکسازی (Cleanup) در useEffect

در برخی موارد، هنگام حذف کامپوننت باید تایمرها، لیسنرها یا درخواست‌های API را متوقف کنیم تا از مشکلات حافظه (Memory Leak) جلوگیری شود. این کار را در تابع بازگشتی useEffect انجام می‌دهیم.

مثال: مدیریت تایمر با useEffect

import React, { useState, useEffect } from "react";
const Timer = () => {
  const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);
    return () => {
      clearInterval(interval); // پاکسازی تایمر هنگام حذف کامپوننت
    };
  }, []);
  return <h1>زمان: {seconds} ثانیه</h1>;
};
export default Timer;

✅ در این مثال، تایمر هر ۱ ثانیه مقدار seconds را افزایش می‌دهد.
✅ هنگام حذف کامپوننت، clearInterval(interval) تایمر را متوقف می‌کند تا از مشکلات حافظه (Memory Leak) جلوگیری شود.

 

۶. چندین useEffect در یک کامپوننت

می‌توان چندین useEffect در یک کامپوننت داشت، هر کدام برای کارهای مختلف.

مثال: یکی برای درخواست API و دیگری برای تغییر عنوان صفحه

import React, { useState, useEffect } from "react";
const Profile = () => {
  const [user, setUser] = useState(null);
  const [count, setCount] = useState(0);
  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users/1")
      .then(response => response.json())
      .then(data => setUser(data));
  }, []);
  useEffect(() => {
    document.title = `شمارنده: ${count}`;
  }, [count]);
  return (
    <div>
      {user ? <h2>نام: {user.name}</h2> : <p>در حال بارگذاری...</p>}
      <button onClick={() => setCount(count + 1)}>افزایش</button>
    </div>
  );
};
export default Profile;

 

useEffect اول فقط هنگام لود شدن اجرا شده و داده‌های کاربر را دریافت می‌کند.
useEffect دوم فقط هنگام تغییر count اجرا شده و عنوان صفحه را تغییر می‌دهد.

 

جمع‌بندی و نکات مهم

useEffect برای مدیریت اثرات جانبی (Side Effects) مانند درخواست API، تایمرها و تغییرات DOM استفاده می‌شود.
✅ بدون آرایه وابستگی، useEffect در هر رندر اجرا می‌شود.
✅ با آرایه خالی [ ] فقط یک‌بار هنگام mount اجرا می‌شود.
✅ با آرایه [dependency] فقط وقتی مقدار آن تغییر کند، اجرا می‌شود.
✅ برای جلوگیری از مشکلات حافظه (Memory Leak)، باید در useEffect پاکسازی (Cleanup) انجام دهیم.
✅ می‌توان چندین useEffect در یک کامپوننت داشت.