Programming Basics SQL HTML CSS JavaScript React Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Linux Learn Typing

Reactالدالة useEffect()

  • مقدمة للدالة useEffect() في React
  • تحضير مشروع للتطبيق العملي
  • تنفيذ أوامر بعد عرض محتوى المكوّن في React
  • تنفيذ أوامر بعد تحديث قيمة المتغير في React

مقدمة للدالة useEffect() في React

تستخدم هذه الدالة لتنفيذ أوامر معينة بعد أن يتم عرض المكوّن في واجهة المستخدم و بعد تحديث قيمة تابعة له.

عادةً ما يتم استخدامها عند الحاجة لجلب معلومات ضرورية للمكوّن. مثلاً عند جلب بيانات من السيرفر من أجل عرضها فيه، عند الحاجة لتشغيل مؤقت ( Timers ) بعد أن يتم عرضه، إذا كان هناك حاجة لإضافة أحداث ( Events ) لعناصر واجهة المستخدم و إزالتها عند إخفائه إلخ..

هذه الدالة هي من ضمن دوال الهووكس ( Hooks ) التي يمكن استخدامها في المكوّن المبني بأسلوب Function Component.


طريقة تضمينها

حتى تتمكن من استخدام الدالة useEffect() يجب تضمينها أولاً كما يلي.

مثال

import { useEffect } from "react";

الشكل العام لاستخدامها

عند استخدام هذه الدالة فإنه يتم ربطها بالشيء الذي سيتم مراقبة قيمته و بالدالة التي من خلالها سيتم تحديث قيمته.

مثال

useEffect(setup, dependency?);
  • setup _ عبارة عن دالة سيتم تنفيذه كلما حصل تغيير ما.
  • dependency _ هو باراميتر إختياري مكانه يمكن تمرير مصفوفة بأسماء المتغيرات المراد إعادة تنفيذ الدالة إذا تغييرت قيمها.

الدالة التي توضع مكان الباراميتر setup يتم تنفيذها بشكل تلقائي عندما يتم عرض محتوى المكوّن لأول مرة و في كل مرة يحصل تغيير في أي قيمة مرتبطة بالمكوّن طالما أنه لم يتم تمرير مصفوفة مكان الباراميتر dependency.

في حال تم تمرير مصفوفة مكان الباراميتر dependency فإنه سيتم تنفيذ الدالة عند عرض محتوى المكوّن لأول مرة فقط و في كل مرة يحصل تغيير في قيمة أحد المتغيرات المذكور إسمها في المصفوفة.

عند كتابة كود الدالة التي توضع مكان الباراميتر setup ستجدنا في آخرها نفعل return بهدف إيقاف عمل أي كود لا يزال يعمل فيها في حال تم إزالة المكوّن من واجهة المستخدم مما يحسّن الأداء و يضمن أن لا يتم تكرار تنفيذ الأوامر بشكل خاطئ.


كم مرة سيتم تنفيذ أوامرها

إذا تم استخدام الدالة useEffect() بدون تمرير مصفوفة مكان الباراميتر الإفتراضي فهذا يعني أنه سيتم تنفيذ الدالة التي نمررها لها كلما تم رصد شيء تغيّر.

الحالة الأولى

useEffect(() => {
    // سيتم تنفيذ الأوامر الموضوعة هنا إذا تم رصد أي تغيير
});

إذا تم استخدام الدالة useEffect() مع تمرير مصفوفة فارغة مكان الباراميتر الإفتراضي فهذا يعني أنه سيتم تنفيذ الدالة التي نمررها لها مرة واحدة فقط.

الحالة الثانية

useEffect(() => {
    // سيتم تنفيذ الأوامر الموضوعة هنا عند عرض المكوّن أول مرة فقط
}, []);

إذا تم استخدام الدالة useEffect() مع تمرير مصفوفة مكان الباراميتر الإفتراضي فيها أسماء متغيرات فهذا يعني أنه سيتم تنفيذ الدالة عند عرض المكوّن لأول مرة و عند حصول أي تغيير في قيمة أحد المتغير.

الحالة الثالثة

useEffect(() => {
    // سيتم تنفيذ الأوامر الموضوعة هنا عند عرض المكوّن أول مرة 
    // variables و عند حصول أي تغيير في قيمة متغير تم تمريره في المصفوفة
}, [variables]);

تحضير مشروع للتطبيق العملي

إتبع الخطوات التالية حتى تقوم ببناء مشروع جديد و تطبق فيه الأمثلة كما فعلنا بالضبط:

  1. قم ببناء مشروع جديد إسمه demo-app.
  2. بداخل المجلد src تجد مجلد إسمه App.js قم بحذف كل الكود الإفتراضي الموجود فيه.
  3. بداخل المجلد src قم بإنشاء مجلد جديد إسمه components لأننا سنضع بداخله مكوّنات.
  4. بداخل المجلد components قم بإنشاء ملف إسمه MyComponent.js لأنه سيمثل مكوّن.

في هذا المشروع قمنا بتجهيز مكوّن واحد هو <MyComponent> لأننا سنقوم لاحقاً بعرض محتواه في المكون <App>.

تنفيذ أوامر بعد عرض محتوى المكوّن في React

في المثال التالي، في المكوّن <MyComponent> قمنا باستخدام الدالة useState() من أجل عرض قيمة متغير إسمه counter في واجهة المستخدم مع إمكانية تحديثها بواسطة دالة إسمها setCounter().

بالإضافة إلى ذلك، قمنا باستخدام الدالة useEffect() من أجل تشغيل مؤقت واحد في كل مرّة مهمته زيادة قيمة المتغير counter واحداً كل ثانية.

في النهاية قمنا بعرض المكوّن <MyComponent> في المكوّن <App> لتجربته.

المثال الأول

/src/components/MyComponent.js
import { useEffect, useState } from "react";

// MyComponent هنا قمنا بتعريف دالة تمثل مكوّن إسمه
function MyComponent() {
    // setCounter() قيمته الأولية 0 و يمكن تحديث قيمته من خلال استدعاء دالة إسمها counter هنا قمنا بتعريف متغير إسمه
    const [counter, setCounter] = useState(0);
    
    // من أجل تنفيذ الدالة الموضوعة فيها مرة واحدة عندما يتم عرض محتوى المكوّن useEffect() هنا قمنا باستدعاء الدالة
    useEffect(() => {
        // واحداً كل ثانية counter هنا قمنا بإنشاء مؤقت مهمته زيادة قيمة المتغير
        const intervalId = setInterval(() => {
            setCounter(value => value + 1);
        }, 1000);

        // هنا قمنا بإيقاف عمل المؤقت في حال تم إزالة المكوّن من واجهة المستخدم
        return () => clearInterval(intervalId);
    }, []);
    
    // counter و قد عرضنا فيه قيمة المتغير MyComponent هنا قمنا بتحضير ما سيتم عرضه عند تضمين المكوّن
    return (
        <>
            <h1>I've rendered {counter} times</h1>
        </>
    );
}

// يمكن الوصول إليه من خارج هذا الملف MyComponent هنا قمنا بجعل المكون
export default MyComponent;
جرب الكود

تمرير المصفوفة الفارغة [] كثاني باراميتر للدالة useEffect() مهم جداً من ناحية تحسين الأداء حيث يضمن أن يتم تنفيذ أوامر الدالة الموضوعة فيها كأول باراميتر مرة واحدة فقط بعد أن يتم عرض محتوى المكوّن في الصفحة.


في المثال التالي، في المكوّن <MyComponent> قمنا باستخدام الدالة useState() من أجل عرض قيمة متغير إسمه windowWidth في واجهة المستخدم مع إمكانية تحديثها بواسطة دالة إسمها setWindowWidth().

بالإضافة إلى ذلك، قمنا باستخدام الدالة useEffect() من أجل إضافة الحدث resize بهدف رصد أي تغيير يحصل في حجم الصفحة، مع الإشارة إلى أنه كلما حصل تغيير في حجمها فإنه سيتم تخزين عرض الصفحة الجديد في المتغير windowWidth.

في النهاية قمنا بعرض المكوّن <MyComponent> في المكوّن <App> لتجربته.

المثال الثاني

/src/components/MyComponent.js
import { useEffect, useState } from "react";

// MyComponent هنا قمنا بتعريف دالة تمثل مكوّن إسمه
function MyComponent() {
    // قيمته الأولية هي عرض شاشة المستخدم windowWidth هنا قمنا بتعريف متغير إسمه
    // setWindowWidth() و يمكن تحديث قيمته من خلال استدعاء دالة إسمها 
    const [windowWidth, setWindowWidth] = useState(window.innerWidth);

    // المربوط به windowWidth و جعلناها تقوم بوضع قيمة عرض الشاشة في المتغير handleResize() هنا قمنا بتعريف الدالة
    function handleResize() {
        setWindowWidth(window.innerWidth);
    }
    
    // من أجل تنفيذ الدالة الموضوعة فيها عند useEffect() هنا قمنا باستدعاء الدالة
    // windowWidth عرض محتوى المكوّن و في كل مرة تتغير فيها قيمة المتغير
    useEffect(() => {
        // عند رصد أي تغير يحصل في حجم الصفحة handleResize() من أجل استدعاء الدالة window للكائن resize هنا قمنا بإضافة الحدث
        window.addEventListener('resize', handleResize);
        // في حال تم إزالة المكوّن من واجهة المستخدم window من الكائن resize هنا قمنا بإزالة الحدث
        return () => {
            window.removeEventListener('resize', handleResize);
        }
    }, []);
    
    // windowWidth و قد عرضنا فيه قيمة المتغير MyComponent هنا قمنا بتحضير ما سيتم عرضه عند تضمين المكوّن
    return (
        <>
            <h1>Window width is {windowWidth}px</h1>
        </>
    );
}

// يمكن الوصول إليه من خارج هذا الملف MyComponent هنا قمنا بجعل المكون
export default MyComponent;
جرب الكود

تنفيذ أوامر بعد تحديث قيمة المتغير في React

في المثال التالي، في المكوّن <MyComponent> قمنا باستخدام الدالة useState() من أجل عرض قيمة متغير إسمه resourceType في واجهة المستخدم مع إمكانية تحديثها بواسطة دالة إسمها setResourceType().

بالإضافة إلى ذلك، قمنا باستخدام الدالة useEffect() من أجل إظهار نافذة تنبيه منبثقة حين يتم عرض محتوى المكوّن بالإضافة إلى كل مرة يتم فيها تحديث قيمة المتغير resourceType.

في النهاية قمنا بعرض المكوّن <MyComponent> في المكوّن <App> لتجربته.

مثال

/src/components/MyComponent.js
import { useEffect, useState } from "react";

// MyComponent هنا قمنا بتعريف دالة تمثل مكوّن إسمه
function MyComponent() {
    // "Home" قيمته الأولية resourceType هنا قمنا بتعريف متغير إسمه
    // setResourceType() و يمكن تحديث قيمته من خلال استدعاء دالة إسمها 
    const [resourceType, setResourceType] = useState("Home");

    // من أجل تنفيذ الدالة الموضوعة فيها useEffect() هنا قمنا باستدعاء الدالة
    // resourceType بالإضافة إلى كل مرة تتغير فيها قيمة المتغير 
    useEffect(() => {
        alert("resourceType is set to " + resourceType);
    }, [resourceType]);

    // MyComponent هنا قمنا بتحضير ما سيتم عرضه عند تضمين المكوّن
    // resourceType و قد عرضنا فيه 3 أزرار بالإضافة إلى قيمة المتغير 
    return (
        <>
            <button onClick={() => setResourceType("Home")}>Home</button>
            <button onClick={() => setResourceType("Posts")}>Posts</button>
            <button onClick={() => setResourceType("Users")}>Users</button>
            <p>{resourceType}</p>
        </>
    );
}

// يمكن الوصول إليه من خارج هذا الملف MyComponent هنا قمنا بجعل المكون
export default MyComponent;
جرب الكود

في المثال السابق مررنا مصفوفة فيها إسم المتغير resourceType للدالة useEffect() لأننا نريدها أن تعيد تنفيذ الدالة الموجودة فيها كلما تغيرت قيمته. لو مررنا مصفوفة فارغة للدالة useEffect() لكان سيتم تنفيذ الدالة مرة واحدة فقط و هي عند أول مرة يتم فيها عرض محتوى المكوّن في واجهة المستخدم.

عند تجربة المثال السابق، ستظهر لك نافذة مبنثقة مرتين و مباشرةً عندما تقوم بتشغيل الكود و سبب ذلك هو أنه عندما يتم رسم المكوّن فإنه سيتم تنفيذ أوامر الدالة useEffect() و بعدها مباشرةً سيتم تنفيذ الدالة useState() التي ستقوم بوضع القيمة الأولية في المتغير resourceType مما سيؤدي إلى إعادة تنفيذ الدالة useEffect() مرة ثانية.