🔹 أولًا: ما هي useEffect ؟
useEffect هي واحدة من أهم Hooks في React.
تُستخدم لتنفيذ أكواد جانبية (Side Effects) داخل المكونات (Components).
🔹 ما معنى “Side Effect” ؟
الـ Side Effect هو أي شيء يحدث خارج عملية “الرندر” الأساسية مثل:
- جلب بيانات من API (fetch data).
- التعامل مع
localStorage. - تشغيل مؤقت (timer أو interval).
- التفاعل مع DOM مباشرة.
- الاشتراك أو الاستماع لأحداث (Event listeners).
🔹 الصيغة العامة (Syntax):
useEffect(() => {
// الكود الذي نريد تنفيذه
}, [dependencies]);JSXشرح الأجزاء:
- الجزء الأول
() => {}
دالة تُنفذ عند تحقق شرط معين (أو مباشرة بعد أول رندر حسب الحالة). - الجزء الثاني
[dependencies]
مصفوفة تضم القيم التي عند تغيّرها يُعاد تنفيذ الكود داخل useEffect.
🔹 الحالات الثلاثة الأساسية لاستخدام useEffect
🟢 الحالة 1: التنفيذ مرة واحدة فقط عند تحميل المكون (mount)
import { useEffect } from "react";
function Example() {
useEffect(() => {
console.log("تم تنفيذ الكود مرة واحدة فقط عند تحميل الصفحة");
}, []); // ← مصفوفة فارغة
return <h2>مرحبًا!</h2>;
}JSX📘 الشرح:
وجود مصفوفة فارغة [] يعني:
نفذ الكود مرة واحدة فقط عند أول تحميل للمكون، ولا تعيده أبدًا.
🧠 الاستخدام الشائع:
- عند جلب البيانات من API لأول مرة.
- عند تشغيل إعدادات أولية (مثل الاتصال بسيرفر أو ضبط حالة).
🟢 الحالة 2: التنفيذ عند تغيّر قيمة معينة
import { useEffect, useState } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("تم تحديث useEffect لأن count تغير:", count);
}, [count]); // ← تعتمد على count
return (
<div>
<p>القيمة الحالية: {count}</p>
<button onClick={() => setCount(count + 1)}>زيادة</button>
</div>
);
}
JSX📘 الشرح:
useEffectستعمل كل مرة تتغير فيها قيمةcount.- مفيد عندما نريد تشغيل كود معين كلما تغيرت حالة معينة.
🧠 الاستخدام الشائع:
- تحديث بيانات في السيرفر عندما تتغير حالة.
- مراقبة تغيّر متغير معين وتشغيل كود بناءً عليه.
🟢 الحالة 3: بدون مصفوفة (تعمل بعد كل عملية رندر)
import { useEffect, useState } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("تم تنفيذ useEffect بعد كل عملية رندر");
});
return (
<div>
<p>القيمة: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
JSX📘 الشرح:
- بدون المصفوفة،
useEffectتعمل كل مرة يحدث فيها رندر. - أي تحديث للحالة سيؤدي إلى تنفيذها مجددًا.
🧠 الاستخدام الشائع:
نادرًا ما نستخدمها هكذا، لأنها تُنفذ كثيرًا.
لكن أحيانًا مفيدة لأغراض التتبع أو التصحيح (debugging).
🔹 تنظيف الـ useEffect (Cleanup)
بعض العمليات تحتاج إيقاف أو تنظيف قبل أن يغلق المكون، مثل:
- إيقاف مؤقت (interval).
- إلغاء اشتراك.
- إزالة مستمع أحداث (Event Listener).
import { useEffect, useState } from "react";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);
// دالة التنظيف
return () => {
clearInterval(timer);
console.log("تم تنظيف المؤقت!");
};
}, []); // تعمل مرة واحدة
return <h2>العداد: {count}</h2>;
}
JSX📘 الشرح:
- عندما يُزال المكون من الصفحة (unmount)، سيتم تشغيل الدالة داخل return.
- هذا يمنع تسرب الذاكرة (memory leaks).
🧠 الاستخدام الشائع:
- تنظيف مؤقتات (intervals, timeouts)
- إلغاء طلبات API
- إزالة event listeners
🔹 مثال عملي شامل
import { useState, useEffect } from "react";
function FetchUser() {
const [user, setUser] = useState(null);
useEffect(() => {
console.log("جلب البيانات من API...");
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((res) => res.json())
.then((data) => setUser(data));
}, []); // مرة واحدة فقط
if (!user) return <p>جاري التحميل...</p>;
return (
<div>
<h2>{user.name}</h2>
<p>البريد: {user.email}</p>
<p>المدينة: {user.address.city}</p>
</div>
);
}
JSX📘 الشرح:
useEffectهنا تستخدم لجلب بيانات المستخدم من API عند تحميل المكون فقط.- يتم تخزين البيانات في
state. - عند اكتمال الجلب، يتم عرض المعلومات.
🧩 ملخص سريع:
| الحالة | شكل المصفوفة | عدد مرات التنفيذ | الاستخدام |
|---|---|---|---|
| تنفيذ مرة واحدة | [] | مرة واحدة | تحميل بيانات أولية |
| تنفيذ عند تغيّر متغير | [variable] | كلما تغيّر | مراقبة حالة معينة |
| تنفيذ بعد كل رندر | لا يوجد مصفوفة | بعد كل تحديث | نادرًا، لأغراض خاصة |
| تنظيف (return) | داخل useEffect | عند الإزالة | إيقاف عمليات مستمرة |