useEffect

🔹 أولًا: ما هي useEffect ؟

useEffect هي واحدة من أهم Hooks في React.
تُستخدم لتنفيذ أكواد جانبية (Side Effects) داخل المكونات (Components).

🔹 ما معنى “Side Effect” ؟

الـ Side Effect هو أي شيء يحدث خارج عملية “الرندر” الأساسية مثل:

  • جلب بيانات من API (fetch data).
  • التعامل مع localStorage.
  • تشغيل مؤقت (timer أو interval).
  • التفاعل مع DOM مباشرة.
  • الاشتراك أو الاستماع لأحداث (Event listeners).
🔹 الصيغة العامة (Syntax):
useEffect(() => {
  // الكود الذي نريد تنفيذه
}, [dependencies]);
JSX
شرح الأجزاء:
  1. الجزء الأول () => {}
    دالة تُنفذ عند تحقق شرط معين (أو مباشرة بعد أول رندر حسب الحالة).
  2. الجزء الثاني [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عند الإزالةإيقاف عمليات مستمرة