مدیریت اثرات جانبی با useEffect
در React
در برنامههای React، برخی عملیات مانند درخواستهای API، کار با localStorage
، تغییر عنوان صفحه، تایمرها و تعامل با DOM را نمیتوان مستقیماً در بدنه کامپوننت انجام داد. برای مدیریت این اثرات جانبی (Side Effects) از هوک useEffect
استفاده میکنیم.
۱. useEffect
چیست و چرا مهم است؟
useEffect
یک هوک React است که اجازه میدهد عملیات جانبی را در کامپوننتهای فانکشنی مدیریت کنیم. این هوک جایگزین متدهای componentDidMount
، componentDidUpdate
و componentWillUnmount
در کامپوننتهای کلاسی شده است.
ساختار کلی useEffect
// کد مربوط به اثر جانبی
return () => {
// کد پاکسازی (اختیاری)
};
}, [dependencies]);
✔ اثر جانبی اجرا میشود: وقتی کامپوننت لود یا بهروزرسانی شود.
✔ پاکسازی انجام میشود: هنگام حذف کامپوننت یا تغییر مقدار در dependencies
.
✔ کنترل اجرا با dependencies
: مشخص میکند که useEffect
چه زمانی اجرا شود.
۲. اجرای useEffect
در هر رندر
اگر useEffect
بدون آرایه وابستگی باشد، در هر بار رندر شدن کامپوننت اجرا خواهد شد.
مثال: نمایش پیام در Console در هر رندر
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 فقط هنگام لود شدن
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
console.log(`مقدار count تغییر کرد: ${count}`);
}, [count]); // فقط وقتی count تغییر کند اجرا میشود.
✅ اگر count
تغییر کند، useEffect
اجرا میشود.
✅ اگر مقدار دیگری (مثلاً یک ورودی متن) تغییر کند، useEffect
اجرا نخواهد شد.
۵. پاکسازی (Cleanup) در useEffect
در برخی موارد، هنگام حذف کامپوننت باید تایمرها، لیسنرها یا درخواستهای API را متوقف کنیم تا از مشکلات حافظه (Memory Leak) جلوگیری شود. این کار را در تابع بازگشتی useEffect
انجام میدهیم.
مثال: مدیریت تایمر با useEffect
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 و دیگری برای تغییر عنوان صفحه
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
در یک کامپوننت داشت.
