الدليل التطبيقي

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

لا يفترض هذا الدليل أي معرفة مسبقة بمكتبة React.

قبل أن نبدأ بالدليل التطبيقي

سنبني لعبة صغيرة خلال هذا الدليل التطبيقي. ربّما قد ترغب بتخطي هذا الدليل لأنّك لا تريد بناء الألعاب، ولكن أعطيها فرصة. إنّ التقنيات التي ستتعلمها في هذا الدليل أساسيّة لبناء أي تطبيق React، وسيعطيك إتقانها فهمًا أعمق لمكتبة React.

فائدة: هذا الدليل مُصمَّم للأشخاص الذين يُفضّلون التعلّم بالممارسة. إن كنت تُفضّل تعلّم المفاهيم من البداية فارجع إلى توثيق React من البداية خطوة بخطوة. قد تجد هذا الدليل متكاملًا مع توثيق React.

هذا الدليل مقسوم إلى عدّة أقسام:

  • يُعطيك قسم الإعداد من أجل الدليل نقطة بداية لمتابعة الدليل.
  • يُعلّمك قسم لمحة عامّة أساسيات React: المكوّنات، والخاصيّات، والحالة.
  • يُعلِّمك قسم إكمال اللعبة أشيع التقنيات في تطوير React.
  • يُعطيك قسم إضافة السفر عبر الزمن نظرة أعمق إلى نقاط القوة الفريدة لمكتبة React.

لا يجب عليك إكمال جميع الأقسام دفعة واحدة للحصول على الفائدة المرجوة من هذا الدليل. حاول الذهاب أبعد ما يمكن حتى ولو كان قسمًا أو قسمين.

لا بأس من نسخ ولصق الشيفرة عند متابعتك مع هذا الدليل، ولكن نوصي أن تكتبها بيدك. سيُساعدك ذلك بتطوير ذاكرتك وبإعطائك فهمًا أعمق لمكتبة React.

ماذا سنبني؟

سنرى في هذا الدليل كيفيّة بناء لعبة إكس-أو (اسمها بالإنجليزيّة tic-tac-toe) باستخدام React.

بإمكانك أن ترى النتيجة النهائيّة لما سنبنيه من هنا. إن كانت الشيفرة غير مفهومة بالنسبة لك أو كنتَ غير متآلف مع صياغة الشيفرة، فلا تقلق! فالهدف من هذا الدليل هو مساعدتك على فهم React وصياغتها.

نوصي بأن تلقي نظرة على لعبة إكس-أو قبل المتابعة. إحدى الميزات التي ستلاحظها وجود قائمة مُرقّمة على يمين لوحة اللعبة. تُعطيك هذه القائمة سجلًّا عن كل التحركات التي حصلت في اللعبة، وتُحدَّث بينما تستمر اللعبة.

تستطيع إغلاق لعبة إكس-أو بعدما تتآلف معها. سننطلق من قالب بسيط في هذا الدليل. خطوتنا التالية هي إتمام الإعداد لكي تستطيع البدء ببناء اللعبة.

المتطلّبات الأساسيّة

سنفترض أنّك متآلف مع HTML و JavaScript، ولكن يجب أن تكون قادرًا على المتابعة حتى ولو كنت قادمًا من لغة برمجة أخرى. سنفترض أنّك متآلف مع المفاهيم البرمجيّة مثل الدوال، والكائنات، والمصفوفات، وبدرجة أقل الأصناف.

إن احتجت لمراجعة JavaScript نوصيك بالرجوع إلى توثيق JavaScript في موسوعة حسوب. لاحظ أنّنا نستخدم بعض الميزات من ES6، وهي إصدار جديد من JavaScript. سنستخدم في هذا الدليل الدوال السهمية، الأصناف، والتصريحين let و const. بإمكانك استخدام Babel REPL لتتحقّق إلى ماذا تُصرَّف شيفرة ES6.

الإعداد من أجل الدليل

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

الخيار الأول للإعداد: كتابة الشيفرة في المتصفح

هذه أسرع طريقة للبدء.

في البداية افتح هذه الشيفرة المبدئيّة في نافذة جديدة. يجب أن تعرض النافذة الجديدة لوحة لعبة إكس-أو وشيفرة React. سنُعدِّل شيفرة React في هذا الدليل.

بإمكانك الآن تجاوز الخيار الثاني للإعداد والذهاب إلى قسم لمحة عامّة للحصول على لمحة عامّة عن React.

الخيار الثاني للإعداد: بيئة التطوير المحليّة

هذا الخيار اختياري وغير مطلوب من أجل هذا الدليل.

اختياري: تعليمات للمتابعة بشكل محلي باستخدام مُحرِّر النصوص المفضّل لديك

يتطلّب هذا الإعداد المزيد من العمل ولكنّه يسمح لك بمتابعة هذا الدليل باستخدام مُحرِّر نصوص من اختيارك. هذه هي الخطوات التي يجب عليك اتباعها:

  • تأكّد من امتلاكك لأحدث إصدار من Node.js.
  • اتبع تعليمات التثبيت لإنشاء تطبيق React لصنع مشروع جديد
npm install -g create-react-app
create-react-app my-app
  • احذف كافة الملفات الموجودة في المجلّد src/‎ للمشروع الجديد (لا تحذف هذا المجلّد، فقط محتوياته).
cd my-app
rm -f src/*
  • أضف ملفًّا يُدعى index.css في المجلّد src/‎ مع وضع شيفرة CSS هذه ضمنه.
  • أضف ملفًّا يُدعى index.js في المجلّد src/‎ مع وضع شيفرة JavaScript هذه ضمنه.
  • أضف هذه الأسطر الثلاثة إلى بداية الملف index.js في المجلّد src/‎:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

إن نفّذت الآن الأمر npm start في مجلّد المشروع وفتحت الرابط http://localhost:3000 في المتصفّح، فبإمكانك أن ترى حقل فارغ للعبة إكس-أو.

نوصي بمتابعة هذه التعليمات لإعداد ميّزة تعليم الصياغة (syntax highlighting) في مُحرِّر النصوص لديك.

ساعدني أنا عالق!

إن وجدت أيّة صعوبات، تحقّق من مصادر مجتمع React، بالأخص دردشة Reactiflux هي طريقة رائعة للحصول على المساعدة بسرعة. إن لم تتلقى أي إجابة أو بقيت عالقًا عند مشكلة ما، يُرجى تقديم المشكلة وسنساعدك في حلّها.

لمحة عامّة

ما هي React؟

React هي مكتبة JavaScript مرنة، وفعّالة، وتصريحيّة لبناء واجهات المستخدم. تُتيح لك تركيب واجهات مستخدم مُعقّدة من قطع معزولة وصغيرة من الشيفرة تُدعى المكوّنات (components).

تمتلك React أنواع مختلفة من المكوّنات، ولكن سنبدأ بالمكوّنات التي هي أصناف فرعية من الصنف React.Component:

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>قائمة تسوق لأجل {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// مثال عن استخدام المكون <ShoppingList name="Mark" />

سنتحدّث قريبًا عن هذه العناصر التي تشبه عناصر XML. نستخدم المكوّنات لنخبر React ما الذي نرغب برؤيته على الشاشة. عندما تتغيّر بياناتنا ستُحدِّث React بكفاءة وتُعيد تصيير مكوّناتنا.

في المثال السابق ShoppingList هي مكوّن React على شكل صنف، وهي من نوع المكوّنات في React. يأخذ المكوّن مُعامِلات تُدعى الخاصيّات props (اختصارًا للكلمة properties)، وتُعيد تسلسل هيكلي من المشاهد التي يجب عرضها عبر التابع render.

يُعيد تابع التصيير render وصفًا لما ترغب برؤيته على الشاشة. تأخذ React الوصف وتعرض النتيجة. يُعيد التابع render بشكلٍ خاص عنصر React، والذي هو وصف بسيط لما ترغب بتصييره. يستخدم معظم مطوري React صياغة خاصّة تُدعى JSX والتي تُسهِّل عمليّة كتابة مثل هذه البُنى. فمثلًا تُحوَّل الصياغة ‎<div />‎ في زمن البناء إلى React.createElement('div')‎. يُكافِئ المثال السابق ما يلي:

return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);

انظر إلى الإصدار الكامل الموسّع من هذا المثال.

إن كنت فضوليًّا فالتابع createElement()‎ مشروح بالتفصيل في مرجع واجهة برمجة التطبيق في React، ولكنّنا لن نستخدمه في هذا الدليل، بل سنستمر في استخدام JSX بدلًا من ذلك.

تأتي JSX مع القوة الكاملة للغة JavaScript. بإمكانك وضع أي تعابير JavaScript ضمن الأقواس بداخل JSX. كل عنصر React هو كائن JavaScript تستطيع تخزينه في متغيّر أو تمريره ضمن برنامجك.

يُصيِّر المكوّن ShoppingList المذكور في الأعلى مكوّنات مُضمَّنة في DOM مثل ‎<div />‎ و ‎<li />‎، ولكن تستطيع تركيب وتصيير مكوّنات React مُخصَّصة أيضًا. على سبيل المثال تستطيع الآن الإشارة إلى كامل قائمة التسوّق عن طريقة كتابة ‎<ShoppingList />‎. يكون كل مكوّن React مُغلّفًا وبإمكانه العمل بشكل مستقل. يسمح لك ذلك ببناء واجهات مستخدم مُعقّدة من مكوّنات بسيطة.

تفحّص شيفرة البدء

إن كنت ستجرّب شيفرة الدليل التطبيقي على متصفحك، افتح شيفرة البدء في نافذة جديدة. أمّا إن كنت ستجرّبها بشكل محلّي فافتح الملف ‎src/index.js‎ الموجود في مجلّد مشروعك (لقد تعرّفت مسبقًا على هذا الملف خلال خطوة الإعداد).

شيفرة البدء هذه هي الأساس لما نبنيه. زوّدناك بتنسيق CSS لكي تحتاج للتركيز فقط على تعلّم React وبرمجة لعبة إكس-أو.

ستلاحظ بتفحّص الشيفرة أنّنا نمتلك ثلاثة مكوّنات:

  • مكوّن المربّع Square.
  • مكوّن لوحة اللعبة Board.
  • مكوّن اللعبة Game.

يُصيِّر المكوّن Square عنصر زر ‎<button>‎ واحد، ويُصيِّر المكوّن Board تسعة مربّعات. يُصيِّر المكوّن Game لوحة مع وجود قيم للتلميح والتي سنُعدّلها لاحقًا. لا يوجد حتى الآن أي مكوّن تفاعلي.

تمرير البيانات عبر الخاصيّات

لتدريب أنفسنا فلنحاول تمرير بعض البيانات من المكوّن Board إلى المكوّن Square.

في التابع renderSquare الموجود في المكوّن Board، غيّر الشيفرة لتمرير خاصيّة تُدعى value إلى المكوّن Square:

class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i} />;
  }

غيّر التابع render في المكوّن Square لإظهار القيم عن طريق وضع ‎{this.props.value}‎ بدلًا من ‎{/* TODO */}‎:

class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    );
  }
}

قبل التغييرات:

tictac-empty-1566a4f8490d6b4b1ed36cd2c11fe4b6-a9336.png

بعد التغييرات: يجب أن ترى عددًا في كل مربّع من الناتج المُصيَّر:

tictac-numbers-685df774da6da48f451356f33f4be8b2-be875.png

انظر إلى كامل الشيفرة عند هذه النقطة.

تهانينا! لقد مرّرت الآن خاصيّة prop من المكوّن Board الأب إلى المكوّن Square الابن. تمرير الخاصيّات هو طريقة عبور المعلومات في تطبيقات React، من المكوّنات الآباء إلى المكوّنات الأبناء.

صنع مكوّن تفاعلي

فلنملأ المكوّن Square بإشارة X عند النقر عليه. فلنغيّر أولًا العنصر button الذي يُعاد من تابع التصيير الخاص بالمكوّن Square إلى ما يلي:

class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={function() { alert('نقرة'); }}>
        {this.props.value}
      </button>
    );
  }
}

إن نقرنا الآن على المربّع فيجب أن نحصل على تحذير في متصفحنا. ملاحظة: لتوفير الكتابة وتجنّب السلوك المُربِك لهذا، سنستخدم صياغة الدوال السهمية من أجل مُعالِجات الأحداث هنا وحتى في باقي أجزاء الشيفرة:

class Square extends React.Component {
 render() {
   return (
     <button className="square" onClick={() => alert('نقرة')}>
       {this.props.value}
     </button>
   );
 }
}

لاحظ كيف أنّنا في الشيفرة ‎onClick={() => alert('click')}‎ نُمرِّر دالة إلى الخاصيّة onClick. وهي تُطلَق فقط عند النقر. من الشائع نسيان ‎() =>‎ وكتابة ‎onClick={alert('click')}‎، والذي يُؤدّي إلى إطلاق التحذير في كل مرّة يُعاد فيها تصيير المكوّن.

في الخطوة التالية سنريد من المكوّن Square أن يتذكر أنّه نُقِر عليه وأن يملأ نفسه بالعلامة X. لتذكر الأشياء تستخدم المكوّنات الحالة state.

تستطيع مكوّنات React أن تمتلك حالة عن طريق تعيين this.state في الدالة البانية لها. يجب اعتبار this.state خاصّة (private) بالنسبة لمكوّن React المُعرَّفة ضمنه. فلنُخزِّن القيمة الحاليّة للمربّع في this.state ونُغيّرها عند النقر عليه.

سنضيف في البداية دالة بانية إلى الصنف لتهيئة الحالة:

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button className="square" onClick={() => alert('نقرة')}>
        {this.props.value}
      </button>
    );
  }
}

ملاحظة: يجب عليك دومًا في أصناف JavaScript أن تستدعي الكلمة super عند تعريف الدالة البانية للصنف الفرعي. يجب أن تبدأ جميع مكوّنات الأصناف في React التي تمتلك دالة بانية constructor باستدعاء super(props)‎.

سنُغيّر الآن تابع التصيير render للمكوّن Square ليعرض قيمة الحالة الحاليّة عند النقر عليه:

  • ضع this.state.value بدلًا من this.props.value بداخل العنصر ‎<button>‎.
  • ضع ‎() => this.setState({value: 'X'})‎ بدلًا من ‎() => alert()‎.
  • ضع الخاصيّتين className و onClick في أسطر منفصلة لسهولة القراءة.

بعد هذه التغييرات سيبدو العنصر ‎<button>‎ المُعاد من تابع التصيير للمكوّن Square كما يلي: