React JS الجزء الرابع – React Hooks

إن المكوّنات أو ما يسمى Components في عالم ReactJS هي بحد ذاتها عناصر مستقلة. ولكل واحد منها خصائصه ووظائفه و بياناته الخاصة به . وهنا نتعرض لمفاهيم جديدة وهي:

  • دورة حياة عناصر أو مكونات React.
    حيث لكل عنصر دورة حياة. تبدأ في اللحظة التي يتم فيها إنشاء هذا المكوّن ووضعه في مكانه في الصفحة. وتنتهي بلحظة إزالته من الصفحة. والمسؤول عن مراقبة وإدارة هذه العملية هي مكتبة ReactJS.
    والجدير بالذكر هنا. أنه كما قمنا بتعريف المكوّن على شكل تابع . فإن مكتبة ReactJS تقوم بتنفيذ هذا التابع في كل مرة يحدث تغيير في الصفحة.
    أي يتم تنفيذ محتوى التابع عند إنشائه. ثم عند حدوث أي تغيير له أو للعناصر التي يحتويها . وهكذا .
    لذلك يجب أخذ هذا الأمر بعين الاعتبار عند كتابة مكوّنات React واستخدامها .
  • الحالة state : والمقصود بها بيانات المكوّن . والتي لا تتغير عند كل مرة يتم تنفيذ التابع الخاص بهذا المكون. حيث قلنا قبل قليل أن التابع يتم تنفيذه أكثر من مرة خلال دورة حياته وقد تصل للمئات وبشكل غير منتظم.

لنشرح هذه المفاهيم من خلال المثال التالي:
سنقوم بكتابة مكوّن React جديد وهو عبارة عن عداد يبدأ بالعد تلقائيا بدون توقف . وليكن إسم هذا المكوّن Counter .
وسنكتب هذا المكوّن في ملف منفصل اسمه Counter.js . ومحتوى هذا الملف كما يلي :

//Counter.js
import React from "react";

function Counter() {
  return <h2>عداد</h2>;
}

export default Counter;
//

حيث في البداية قمنا بتضمين المكتبة React . ثم كتبنا التابع Counter الذي يمثل المكوّن الجديد . وهذا التابع يقوم بإرجاع وسم h2 يحتوي كلمة عداد .
ثم في النهاية قمنا بتصدير المكون Counter عبر التعليمة export وذلك ليصبح هذا المكوّن أو التابع متاح للملفات الأخرى في المشروع.

ثم نقوم بوضع هذ المكوّن الجديد ضمن محتوى المكون App الذي قمنا بإنشائه سابقا في هذه الدورة.
وذلك بتضمين المكوّن Counter ضمن الملف App.js , ليصبح الكود الخاص بالمكوّن App كما في الشكل :

//App.js
import React from "react";
import Counter from "./Counter";

function App() {
  const cssStyle = {
    width: "100%",
    padding: "25px 0px",
    textAlign: "center",
  };

  return (
    <div style={cssStyle}>
      <Counter />
    </div>
  );
}

export default App;
//

نلاحظ أننا استخدمنا المكوّن Counter وكأنه وسم HTML ضمن محتوى المكوّن App . ولكن في الحقيقة هذا ليس كود HTML . وإنما هذه هي الطريقة التي نعتمدها لاستخدام هذه المكونات في بيئة ReactJS.
حيث نقوم بتعريف المكوّن على شكل تابع . ونستخدم هذا المكون بنفس الطريقة التي نكتب بها وسم HTML.
مع مراعاة أنه يجب أن يكون الحرف الأول من اسم المكوّن هو حرف كبير.
لنقوم بتشغيل هذا المثال بكتابة npm start في موجه الأوامر لنرى النتيجة :

حتى الآن لم نعرض في الصفحة سوى كلمة واحدة وهي عداد .
ولكن نريد من هذا العداد أن يبدأ بالعد . وهنا سنحتاج متحول من نوع رقم صحيح يبدأ بالقيمة 0 ويتزايد كل فترة زمنية محددة.
ولكن لو أردنا تعريف متحول جديد . كيف سنجعل هذا المتحول يبدأ بالعد بشكل منتظم؟
لهذا السبب يجب أن نتعرف على مفهوم جديد وهو React Hooks.

React Hooks :

hook تعني الخطّاف . والذي يشبه رأس صنارة الصيد. وهذا الاسم للتشبيه فقط .
حيث React Hooks هي مجموعة من التوابع التي تعمل بدور يشبه دور الخطاف ليسمح لنا بالوصول إلى حالة المكوّن state و كذلك تسمح لنا بكتابة أوامر ليتم تنفيذها في أوقات تتعلق بدورة حياة مكوّنات React. على سبيل المثال عندما نريد تنفيذ أمر لمرة واحدة فقط عند وضع المكوّن في الصفحة .
وللملاحظة فإن هذه التوابع فقط تعمل في حال كتبنا المكوّن على شكل تابع Functional Component . وليس عندما نكتبه على شكل نوع Class Component .

لنبدأ بشرح أهم هذه التوابع أو Hooks :

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

//App.js
import React from "react";

function Counter() {
  const [count, setCount] = React.useState(0);
  

  return <h2 style={{ color: "#FF0000" }}>{count}</h2>;
}
//...

هنا قمنا بتعريف متحول اسمه count . ولكن ليس بالطريقة المتعارف عليها لتعريف المتحولات .
حيث التابع useState والذي هو جزء من المكتبة React عند استدعائه يعيد لنا مصفوفة . الجزء الأول منها هو المتحول . والجزء الثاني منها هو تابع لتغيير قيمة المتحول . بينما القيمة التي نمررها للتابع هي القيمة الأولية للمتحول .
وهذه العملية الغريبة ضرورية بالنسبة لعالم ReactJS . وذلك لأن حالة المكوّن state لايمكن تغييرها بشكل مباشر . وإنما نستخدم تابع خاص لتغييرها .
وبما أننا عرّفنا المتحول count ليكون جزء من الحالة state . لايمكن أن نغير قيمة هذا المتحول بشكل مباشرة. وإنما نستخدم التابع الذي يعيده التابع useState . والذي في حالتنا هذه اخترنا له الاسم setCount .
ثم وضعنا قيمة هذا المتحول ضمن الوسم h2 الذي يعيده التابع في خرجه ليتم عرضه في الصفحة .
وعندما ننظر في الصفحة سنجد في منتصف الشاشة الرقم 0 ثابت لا يتغير وهو القيمة الأولية للمتحول count .

والآن لنستطيع جعل هذا المتحول يتغير كل فترة زمنية محددة سنحتاج التعرف على المفهوم الجديد التالي.

useEffect : هذا التابع أيضا من توابع React Hooks . ووظيفته إضافة عملية ما ليتم تنفيذها في وقت ما خلال دورة حياة عناصر React .
لتبسيط الأمور سنأخذ الحالات التالية :
– الحالة الأولى : عندما نريد تنفيذ تابع معين وليكن اسمه init مرة واحدة عند إنشاء المكوّن ولحظة وضعه في صفحة الانترنت.
هنا نستخدم الطريقة التالية :

//
  function init() {
    
  }

  React.useEffect(init, []);
//

حيث قمنا باستدعاء التابع useEffect من المكتبة React . ونمرر له في البداية أو القيمة الأولى هي التابع الذي نريد تنفيذه .
أما القيمة الثانية فهي مصفوفة من المتحولات. والهدف منها هو أن يتم إعادة تنفيذ هذا التابع init عند أي تغيير في قيمة المتحولات التي تحويها المصفوفة .
ولكن في حالتنا هذه المصفوفة فارغة . وهذا يعني أن التابع لن يتم تنفيذه مرة أخرى . وإنما يتم تنفيذه فقط لحظة إنشاء المكوّن .

– الحالة الثانية : عندما نريد تنفيذ التابع عند ظروف محددة . وهذا ما نريده بالنسبة للعداد . حيث نريد زيادة قيمة العداد كل فترة زمنية مثلا كل ثانية أو 1000 ميلي ثانية . وذلك يكون بالشكل التالي :

//
  function increment() {
    setCount(count + 1);
  }

  function init() {
    setTimeout(increment, 1000);
  }
//

هنا قمنا بكتابة تابع بسيط اسمه increment وظيفته زيادة قيمة العداد. وذلك بتغيير قيمة المتحول count . وكما تعلما أنه لايمكن تغيير قيمته بشكل مباشر . لذلك نستخدم التابع setCount لتغيير قيمة count لتصبح count + 1 .

ثم في التابع init قمنا بإنشاء مؤقت يقوم بتنفيذ التابع increment بعد ثانية . وبالتالي زيادة قيمة العداد بعد ثانية .
ولجعل هذه العملية تتكر . نعود لمفهوم useEffect . حيث قلنا أننا نمرر للتابع مصفوفة من المتحولات . التي عندما تتغير قيمتها يتم تنفيذ التابع المرفق معه.
وفي حالتنا هذه نمرر المتحول count . حيث عندما تتغير قيمته يتم تنفيذ التابع init مرة ثانية من جديد. وكذا
وبالتالي يصبح الكود الكامل للعداد كما في الشكل :

//Counter.js
import React from "react";

function Counter() {
  const [count, setCount] = React.useState(0);

  function increment() {
    setCount(count + 1);
  }

  function init() {
    setTimeout(increment, 1000);
  }

  React.useEffect(init, [count]);

  return <h2>{count}</h2>;
}

export default Counter;
//

والآن بالعودة لمستعرض الانترنت نلاحظ أن في منتصف صفحة الانترنت يوجد رقم يتغير كل ثانية كما في الشكل :

وهكذا نكون قد وصلنا لنهاية هذا الجزء من الدورة.
حيث تعلمنا كيفية التعامل مع حالة المكوّن state . وتعرفنا على أهم توابع React Hooks .
وفي الجزء القادم سنتعرف على المزيد من هذه التوابع.