<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: React</title><link>https://academy.hsoub.com/programming/javascript/react/page/3/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: React</description><language>ar</language><item><title>&#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; &#x628;&#x646;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1071/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_11/2.png.ae2086e1c74e3f53b4dc3085d56427c8.png" /></p>
<p>
	قبل أن نبدأ البرمجة، سنستعرض بعض المبادئ المعتمدة في تطوير الويب من خلال الاطلاع على هذا التطبيق النموذجي عبر الرابط: <a href="https://studies.cs.helsinki.fi/exampleapp" rel="external nofollow">studies.cs.helsinki.fi/exampleapp</a>.
</p>

<p>
	صممت هذه التمارين لتوضيح بعض المفاهيم الأساسية في المنهاج، وليس لتقديم الطريقة التي ينبغي أن تبنى بها تطبيقات الويب. فهي على العكس تمامًا، ستشرح بعض التقنيات القديمة في تطوير الويب والتي يمكن أن تعتبر في أيامنا هذه عادات برمجية سيئة. مع هذا ستتعلم كتابة الشيفرة بالأسلوب الأنسب في القسم 1.
</p>

<p>
	استعمل متصفح Chrome الآن ودائمًا خلال رحلتك في هذا المنهاج. ثم استخدمه في فتح التطبيق النموذجي، قد يستغرق ذلك وقتًا. القاعدة الأولى في تطوير الويب: ابق طرفية التطوير (Development Console) مفتوحةً دومًا في متصفحك. إن كنت تعمل على نظام التشغيل Windows اضغط زر <strong>F12</strong> أو أزرار <strong>ctrl-shift-i</strong> معًا لفتحه. أما في نظام التشغيل MacOS فاضغط زر <strong>F12</strong> أو الأزرار <strong>Option-cmd-i</strong> معًا.
</p>

<p>
	قبل المتابعة، اكتشف طريقة فتح طرفية التطوير على حاسوبك، وتذكر أن تبقيها مفتوحةً دومًا عندما تعمل على تطوير تطبيقات الويب. ستظهر طرفية التطوير بالشكل التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="53633" href="https://academy.hsoub.com/uploads/monthly_2020_11/console_001.png.304d17d0842f6805585caa97f8786c53.png" rel=""><img alt="console_001.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53633" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_001.png.304d17d0842f6805585caa97f8786c53.png"></a>
</p>

<p>
	تأكد أن نافذة (Network) مفتوحة، ثم ألغ تفعيل خيار (Disable Cache).
</p>

<p>
	إن حفظ سجل العمل (log) قد يكون مفيدًا، إذ سيحفظ سجلات تنفيذ التطبيق عند إعادة تحميل الصفحة.
</p>

<p>
	<strong>لاحظ جيدًا:</strong> إن أكثر النوافذ أهميةً في الطرفية هي (Network)، و سنستخدمها بكثرة في البداية.
</p>

<h2>
	الطلبية من النوع HTTP GET
</h2>

<p>
	يتواصل الخادم (Server) مع المتصفح باستخدام بروتوكول HTTP، وتعرض نافذة (Network) تفاصيل هذا التواصل. فعندما نطلب إعادة تحميل الصفحة ( الزر <strong>F5</strong> أو الرمز <strong>↺</strong> على المتصفح)، ستُظهر الطرفية أن حدثين قد وقعا:
</p>

<ul>
	<li>
		<p>
			جلب المتصفح محتوى صفحة التطبيق من الخادم.
		</p>
	</li>
	<li>
		<p>
			نزّل المتصفح الصورة Kuva.png.
		</p>
	</li>
</ul>

<p style="text-align: center;">
	<img alt="network_window_002.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53651" data-unique="t4wv189ep" src="https://academy.hsoub.com/uploads/monthly_2020_11/network_window_002.png.d1573eb80223532307388febb331ee85.png">]
</p>

<p>
	عليك تكبير شاشة الطرفية لترى ذلك إن كانت شاشة العرض صغيرة. ستظهر لك معلومات أكثر عند النقر على الحدث الأول:
</p>

<p style="text-align: center;">
	<img alt="network_window_headers_003.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53652" data-unique="ehfun7mw2" src="https://academy.hsoub.com/uploads/monthly_2020_11/network_window_headers_003.png.e6a6fde946b0dcc9139265baa9736156.png">
</p>

<p>
	يظهر القسم العلوي (General)، أن المتصفح قدم طلبًا إلى العنوان: <a href="https://fullstack-exampleapp.herokuapp.com/" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com</a> مستخدما أسلوب GET، وأن الطلب كان ناجحًا لأن الخادم استجاب معيدًا رمز حالة (Status Code) قيمته 200.
</p>

<p>
	توجد العديد من الترويسات (<a href="https://en.wikipedia.org/wiki/List_of_HTTP_header_fields" rel="external nofollow">Headers</a>) للطلب والاستجابة، يُظهر الشكل التالي بعضها:
</p>

<p style="text-align: center;">
	<img alt="headers_004.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53648" data-unique="jht2h8o3s" src="https://academy.hsoub.com/uploads/monthly_2020_11/headers_004.png.e9d4cd0b46dc3b994f2b63783c4e3756.png">
</p>

<p>
	تعطينا ترويسات الاستجابة (Response headers) معلومات عدة، مثل حجم الاستجابة مقدرة بالبايت والوقت الدقيق لها. كذلك الأمر تخبرنا ترويسة نوع المحتوى (Content_Type) أن الاستجابة كانت على شكل ملف نصي بصيغة utf-8، وتحدد المحتوى الذي سيظهر بتنسيق HTML. وبهذا يعلم المتصفح أن الاستجابة ستكون على شكل صفحة HTML قياسية، ليعرضها كصفحة ويب.
</p>

<p>
	تُظهر نافذة (Response) بيانات الاستجابة على شكل صفحة HTML. حيث يحدد القسم <code>Body</code> هيكل الصفحة التي ستُعرض على الشاشة. وتحوي صفحة HTML أيضًا العنصر <code>Div</code> الذي يضم عناصر أخرى مثل معرّف العنوان <code>h1</code> والرابط <code>a</code> إلى صفحة الملاحظات ومعّرف الصور<code>img</code> وأخيرًا معرّف الفقرة <code>p</code> الذي يُظهر في مثالنا عدد الملاحظات التي تم إنشاؤها.
</p>

<p style="text-align: center;">
	<img alt="response_window_005.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53656" data-unique="d40zihxos" src="https://academy.hsoub.com/uploads/monthly_2020_11/response_window_005.png.272da6ad41c361b17dd73d6fbe9cf793.png">
</p>

<p>
	ونظرًا لوجود معرّف الصور <code>img</code>، أرسل المتصفح طلب HTTP جديد إلى الخادم لإحضار الصورة التي عنوانها kuva.png. يُظهر الشكل التالي تفاصيل الطلب:
</p>

<p style="text-align: center;">
	<img alt="headers_image_fetch_006.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53649" data-unique="5p9f8i5ae" src="https://academy.hsoub.com/uploads/monthly_2020_11/headers_image_fetch_006.png.542ae66b40921571792e970624908fcd.png">
</p>

<p>
	أُرسل طلب HTTP-GET إلى العنوان: <a href="https://fullstack-exampleapp.herokuapp.com/kuva.png" ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/kuva.png</a> وتخبرنا ترويسات الاستجابة أن حجم الاستجابة يعادل 89350 بايت، ومحتواها صورة بصيغة png. يستخدم المتصفح هذه المعلومات لإظهار الصورة بشكل صحيح على الشاشة.
</p>

<p>
	يمثل <a href="https://www.geeksforgeeks.org/unified-modeling-language-uml-sequence-diagrams/" rel="external nofollow">المخطط التتابعي</a> التالي، سلسلة الأحداث التي بدأت بفتح الصفحة https://fullstack-exampleapp.herokuapp.com:
</p>

<p style="text-align: center;">
	<img alt="follow_diagram_007.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53661" data-unique="u82g7kv2e" src="https://academy.hsoub.com/uploads/monthly_2020_11/follow_diagram_007.png.033775e402d3d736b7887ef516ad70f4.png">
</p>

<p>
	أرسل المتصفح في البداية، طلبًا إلى الخادم من نوع HTTP-GET للحصول على شيفرة HTML للصفحة. يخبر معرّف الصور <code>img</code> الموجود في شيفرة HTML المتصفح أن يحضر صورة بعنوان kuva.png. ثم يعالج المتصفح شيفرة HTML والصورة ويظهرهما على الشاشة. مع ذلك يصعب ملاحظة أن معالجة صفحة HTML بدأت قبل أن يحضر المتصفح الصورة من الخادم.
</p>

<h2>
	تطبيقات الويب التقليدية
</h2>

<p>
	يماثل عمل صفحة التطبيق النموذجي السابق عمل تطبيقات الويب التقليدية. فعند الدخول إلى الصفحة، يحضر المتصفح من الخادم ملف HTML الذي يُنسِّق طريقة عرض الصفحة ومحتواها النصي.
</p>

<p>
	لقد بنى الخادم هذا المستند بطريقة ما. فقد يكون المستند عبارة عن مستند نصي ذي محتوًى ثابت محفوظ على الخادم. كما يمكن للخادم أيضًا أن يبني مستند HTML ديناميكيًا وفقًا للتعليمات الموجودة في شيفرة التطبيق مستخدمًا على سبيل المثال، بيانات موجودة في قاعدة بيانات محددة. فشيفرة ملف HTML في التطبيق النموذجي السابق مثلًا، كُتبت ديناميكيًا من قبل الخادم، كونه احتوى معلومات تدل على عدد الملاحظات التي دونت في الصفحة.
</p>

<p>
	تظهر شيفرة HTML لصفحة التطبيق النموذجي بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_8" style=""><span class="kwd">const</span><span class="pln"> getFrontPageHtml </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">noteCount</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pun">(`</span><span class="pln">
    </span><span class="pun">&lt;!</span><span class="pln">DOCTYPE html</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">html</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">head</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">head</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">body</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">'container'</span><span class="pun">&gt;</span><span class="pln">
          </span><span class="pun">&lt;</span><span class="pln">h1</span><span class="pun">&gt;</span><span class="typ">Full</span><span class="pln"> stack example app</span><span class="pun">&lt;/</span><span class="pln">h1</span><span class="pun">&gt;</span><span class="pln">
          </span><span class="pun">&lt;</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">number of notes created $</span><span class="pun">{</span><span class="pln">noteCount</span><span class="pun">}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
          </span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">'/notes'</span><span class="pun">&gt;</span><span class="pln">notes</span><span class="pun">&lt;/</span><span class="pln">a</span><span class="pun">&gt;</span><span class="pln">
          </span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">'kuva.png'</span><span class="pln"> width</span><span class="pun">=</span><span class="str">'200'</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
        </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">body</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">html</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">`)</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> 

app</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> page </span><span class="pun">=</span><span class="pln"> getFrontPageHtml</span><span class="pun">(</span><span class="pln">notes</span><span class="pun">.</span><span class="pln">length</span><span class="pun">)</span><span class="pln">
  res</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="pln">page</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	بالطبع ليس عليك استيعاب الشيفرة المكتوبة حاليًا.
</p>

<p>
	يُحفظ محتوى صفحة HTML على شكل قالب نصي (Template String) أو على شكل سلسلة نصية تسمح على سبيل المثال، بتحديد قيمة المتغيرات الموجودة ضمنها. فالقسم الديناميكي (القابل للتغيير) في صفحة التطبيق النموذجي السابق هو القسم الذي يشير إلى عدد الملاحظات المدونة و يدعى <code>notecount</code>. يُستبدَل هذا القسم بالعدد الفعلي للملاحظات <code>notes.length</code> ضمن القالب النصي للصفحة. لاحظ أن وجود شيفرة HTML ضمن الشيفرة السابقة هو أمر غير مُحبَّذ، لكن مبرمجي مدرسة PHP التقليدية يعتبرون ذلك شيئًا طبيعيًا.
</p>

<p>
	يُعتبَر المتصفح في تطبيقات الويب التقليدية "محايدًا". فوظيفته فقط إحضار بيانات HTML من الخادم الذي يقع على عاتقه القيام بكل العمليات المنطقية التي يحتاجها التطبيق. يمكن بناء الخادم باستعمال لغة Java Spring كالخادم الذي استخدم في منهاج <a href="https://courses.helsinki.fi/fi/tkt21007/119558639" rel="external nofollow">Web-palvelinohjelmointi</a> لجامعة هلسنكي، أو استعمال لغة Python Flask كمنهاج <a href="https://materiaalit.github.io/tsoha-18" rel="external nofollow">tietokantasovellus</a> ، أو باستعمال <a href="http://rubyonrails.org/" rel="external nofollow">Ruby and Rails</a>. سيستعمل التطبيق السابق <a href="https://expressjs.com/" rel="external nofollow">Express</a> من Node.j.s، وسيستخدم هذا المنهاج التقنيتين السابقتين لبناء الخادم.
</p>

<h2>
	تشغيل التطبيق من المتصفح
</h2>

<p>
	ابق طرفية التطوير مفتوحةً، واحذف ما فيها بالنقر على ?. عندما تنقر الآن على رابط <a href="https://fullstack-exampleapp.herokuapp.com/notes" rel="external nofollow">notes</a>، سيرسل المتصفح أربع طلبات HTTP:
</p>

<p style="text-align: center;">
	<img alt="request_types_008.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53655" data-unique="p60cvcvp5" src="https://academy.hsoub.com/uploads/monthly_2020_11/request_types_008.png.fbf99ac32eeb1c7292564a05452ab2d5.png">
</p>

<p>
	لهذه الطلبات أنواع مختلفة. ويمثل النوع (مستند document)، شيفرة HTML للصفحة ويظهر بالشكل التالي:
</p>

<p style="text-align: center;">
	<img alt="request_type_document_009.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53654" data-unique="xh03ncyx8" src="https://academy.hsoub.com/uploads/monthly_2020_11/request_type_document_009.png.86b81a2c998769558f211eb1dc7d088e.png">
</p>

<p>
	الآن، عندما نقارن الصفحة الظاهرة على المتصفح مع شيفرة HTML التي يعيدها الخادم، سنلاحظ أن الشيفرة لا تحتوي على قائمة الملاحظات. تحتوي ترويسة القسم <code>html</code> من الشيفرة على العنصر <code>script</code> الذي يطلب من المتصفح إحضار ملف JavaScript يدعى main.js. تظهر شيفرة JavaScript كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_10" style=""><span class="kwd">var</span><span class="pln"> xhttp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XMLHttpRequest</span><span class="pun">()</span><span class="pln">

xhttp</span><span class="pun">.</span><span class="pln">onreadystatechange </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">readyState </span><span class="pun">==</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">status </span><span class="pun">==</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">responseText</span><span class="pun">)</span><span class="pln">
    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">var</span><span class="pln"> ul </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">)</span><span class="pln">
    ul</span><span class="pun">.</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="str">'class'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'notes'</span><span class="pun">)</span><span class="pln">

    data</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> li </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">)</span><span class="pln">

      ul</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">li</span><span class="pun">)</span><span class="pln">
      li</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">document</span><span class="pun">.</span><span class="pln">createTextNode</span><span class="pun">(</span><span class="pln">note</span><span class="pun">.</span><span class="pln">content</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">})</span><span class="pln">

    document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'notes'</span><span class="pun">).</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">ul</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

xhttp</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'GET'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/data.json'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
xhttp</span><span class="pun">.</span><span class="pln">send</span><span class="pun">()</span></pre>

<p>
	لا تهمنا حاليًا التفاصيل الواردة في الشيفرة السابقة، لكن جزء منها قد كتب لتجميل مظهر الصور والنصوص (من المرجح أن نبدأ كتابة شيفرات في القسم 1). ونلفت انتباهك أن كتابة الشيفرة السابقة لا تتناسب إطلاقًا وتقنيات كتابة الشيفرات التي ستتعلمها في هذا المنهاج.
</p>

<p>
	قد يتساءل البعض عن مغزى استخدام كائن <code>xhttp</code> بدلًا من الأسلوب الحديث لجلب البيانات. إن السبب الرئيسي هو أننا لانريد الآن إظهار ما وعدنا به، و أيضًا للدور الثانوي الذي تلعبه هذه الشيفرة في هذا القسم من المنهاج. لكننا سنطبق في القسم الثاني الطرق الأحدث في إرسال الطلبات إلى الخادم.
</p>

<p>
	بعد إحضار ماطلبه عنصر<code>script</code> مباشرةً، يبدأ المتصفح بتنفيذ الشيفرة. حيث يشير السطرين الأخيرين إلى أن المتصفح سيرسل طلبا من نوع HTTP-GET إلى العنوان التالي data.json/ على الخادم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_12" style=""><span class="pln">xhttp</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'GET'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/data.json'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
xhttp</span><span class="pun">.</span><span class="pln">send</span><span class="pun">()</span></pre>

<p>
	سنكون بذلك قد وصلنا إلى آخر طلب سيظهر ضمن النافذة (Network). يمكننا بطبيعة الحال الوصول إلى هذا العنوان مباشرة من نافذة المتصفح كما في الشكل التالي:
</p>

<p style="text-align: center;">
	<img alt="json_data_in_browser_010.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53650" data-unique="aatrflqud" src="https://academy.hsoub.com/uploads/monthly_2020_11/json_data_in_browser_010.png.3274a5525a531805079d63de3ca5ece7.png">
</p>

<p>
	سنحصل عند فتح العنوان السابق على الملاحظات مكتوبة بصيغة بيانات غير معالجة (raw data) كالتي يستخدمها JSON. لا يمكن للمتصفح في الحالة الطبيعية إظهار هذه البيانات بشكل واضح، لذلك يمكن تثبيب إضافة (Plugin) للتعامل مع هذه الصيغة من البيانات. ثبت على سبيل المثال JSONView على متصفح Chrome ثم أعد تحميل الصفحة. ستظهر البيانات الآن بشكل مفهوم.
</p>

<p style="text-align: center;">
	<img alt="rawdata_jsonview_011.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53653" data-unique="y5oct0sc6" src="https://academy.hsoub.com/uploads/monthly_2020_11/rawdata_jsonview_011.png.69e895d7089fe394e92a99902854ec5a.png">
</p>

<p>
	إذًا، تُحمِّل شيفرة HTML في صفحة الملاحظات Notes بيانات JSON تحتوي على الملاحظات، وترتبها على شكل قائمة نقاط. ويتم ذلك بتنفيذ الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_14" style=""><span class="kwd">const</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">responseText</span><span class="pun">)</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> ul </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">)</span><span class="pln">
ul</span><span class="pun">.</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="str">'class'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'notes'</span><span class="pun">)</span><span class="pln">

data</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">var</span><span class="pln"> li </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">)</span><span class="pln">

  ul</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">li</span><span class="pun">)</span><span class="pln">
  li</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">document</span><span class="pun">.</span><span class="pln">createTextNode</span><span class="pun">(</span><span class="pln">note</span><span class="pun">.</span><span class="pln">content</span><span class="pun">))</span><span class="pln">
</span><span class="pun">})</span><span class="pln">

document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'notes'</span><span class="pun">).</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">ul</span><span class="pun">)</span></pre>

<p>
	تُنشأ الشيفرة بداية قائمة غير مرتبة <code>ul</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_16" style=""><span class="kwd">var</span><span class="pln"> ul </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">)</span><span class="pln">
ul</span><span class="pun">.</span><span class="pln">setAttribute</span><span class="pun">(</span><span class="str">'class'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'notes'</span><span class="pun">)</span></pre>

<p>
	ثم تضيف العنصر<code>li</code> (الذي يمثل عنصرًا من قائمة نقاط) لكل ملاحظة، وتضع بداخله محتويات الحقل <code>content</code> فقط من الملاحظة. أما القيم الزمنية الموجودة في الحقل <code>date</code>، فلن تستخدم هنا.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_18" style=""><span class="pln">data</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">var</span><span class="pln"> li </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">)</span><span class="pln">

  ul</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">li</span><span class="pun">)</span><span class="pln">
  li</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">document</span><span class="pun">.</span><span class="pln">createTextNode</span><span class="pun">(</span><span class="pln">note</span><span class="pun">.</span><span class="pln">content</span><span class="pun">))</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	افتح الآن النافذة Console ضمن طرفية التطوير كالتالي:
</p>

<p style="text-align: center;">
	<img alt="console_window_012.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53639" data-unique="fpz8afu7l" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_window_012.png.e325c6f30bac0435c3c2238befadbc62.png">
</p>

<p>
	سيظهر النص كاملًا عند النقر على المثلث الصغير في بداية السطر:
</p>

<p style="text-align: center;">
	<img alt="console_window_log_013.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53640" data-unique="so2ukuq0g" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_window_log_013.png.8c1fca538d30e95819ecfd5b4f15ed0c.png">
</p>

<p>
	نتج النص السابق عن تعليمة <code>console.log</code> الموجودة في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_20" style=""><span class="kwd">const</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">responseText</span><span class="pun">)</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span></pre>

<p>
	وبالتالي ستطبع الشيفرة تلك البيانات في الطرفية بعد استقبالها من الخادم. ستعتاد التعامل مع نافذة Console ومع تعليمة <code>Console.log</code> خلال مسيرتك في هذا المنهاج.
</p>

<h2>
	معالج الأحداث (Event Handler) و دوال رد النداء (Callback functions)
</h2>

<p>
	ستبدو لك بنية هذه الشيفرة غريبةً نوعا ما:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5805_9" style=""><span class="kwd">var</span><span class="pln"> xhttp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XMLHttpRequest</span><span class="pun">()</span><span class="pln">

xhttp</span><span class="pun">.</span><span class="pln">onreadystatechange </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// الشيفرة التي ستعالج استجابة الخادم</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

xhttp</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'GET'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/data.json'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
xhttp</span><span class="pun">.</span><span class="pln">send</span><span class="pun">()</span></pre>

<p>
	لقد أُرسِل الطلب إلى الخادم في آخر سطر من الشيفرة، لكن التعليمات التي تعالج الاستجابة أتت في البداية. ما الذي يحدث؟ في هذا السطر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_25" style=""><span class="pln">xhttp</span><span class="pun">.</span><span class="pln">onreadystatechange </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	تم تحديد معالج (handler) للحدث <code>onreadystatechange</code>، الخاص بالكائن <code>xhttp</code>، أثناء إرسال الطلب إلى الخادم. فعندما تتغير حالة هذا الكائن، يستدعي المتصفح الدالة التي تمثل معالج هذا الحدث، ثم تتحق الدالة من أن قيمة الخاصة 'readystate' تساوي 4 (والتي تشير إلى أن العملية قد اكتملت)، وأن قيمة رمز الحالة (status code) لبروتوكول HTTP عند الاستجابة تساوي 200.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5805_11" style=""><span class="pln">xhttp</span><span class="pun">.</span><span class="pln">onreadystatechange </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">readyState </span><span class="pun">==</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">status </span><span class="pun">==</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// الشيفرة التي ستعالج استجابة الخادم </span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إن هذا الأسلوب في استدعاء معالجات الأحداث شائع جدًا في لغة JavaScript، وتسمى دالة معالج الأحداث (نداء <a href="https://developer.mozilla.org/en-US/docs/Glossary/Callback_function" rel="external nofollow">callback</a>). لا تستدعي شيفرة التطبيق الدوال بنفسها، بل يستدعي المتصفح الذي يعتبر (بيئة التشغيل) في هذه الحالة، الدوال في الوقت المناسب وذلك عندما يقع الحدث.
</p>

<h2>
	نموذج كائن المستند (Document Object Model DOM)
</h2>

<p>
	يمكنك التفكير بصفحة HTML على أنها بنًى شجرية متداخلة.
</p>

<pre class="ipsCode">html
  head
    link
    script
  body
    div
      h1
      div
        ul
          li
          li
          li
      form
        input
        input
</pre>

<p>
	يمكن مشاهدة بنًى كهذه ضمن الطرفية /نافذة Elements:
</p>

<p style="text-align: center;">
	<img alt="console_elements_014.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53636" data-unique="2xpoxsyoc" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_elements_014.png.22aaacfee8dcdf1ba0c90d14f94629ae.png">
</p>

<p>
	تعتمد آلية عمل المتصفح على فكرة تمثيل عناصر HTML على شكل شجرة. وبما أن نموذج كائن المستند DOM هو واجهة تطبيقات برمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>، قادرة على تعديل العناصر الشجرية لصفحة الويب برمجيًا، فقد استخدمت شيفرة JavaScript التي رأيناها سابقًا الواجهة DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> لإضافة لائحة بالملاحظات المدونة في الصفحة.
</p>

<p>
	تضيف الشيفرة التالية عقدة جديدة للمتغيِّر <code>ul</code>، ثم تضيف عقدًا ضمنه (عقد أبناء):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_30" style=""><span class="kwd">var</span><span class="pln"> ul </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">)</span><span class="pln">

data</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">var</span><span class="pln"> li </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">)</span><span class="pln">

  ul</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">li</span><span class="pun">)</span><span class="pln">
  li</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">document</span><span class="pun">.</span><span class="pln">createTextNode</span><span class="pun">(</span><span class="pln">note</span><span class="pun">.</span><span class="pln">content</span><span class="pun">))</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	وأخيرًا، بعد اكتمال فرع الشجرة الذي يمثله المتحول <code>ul</code>، سنضمه إلى شجرة HTML الممثلة لكامل صفحة الويب في مكانه المناسب.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_32" style=""><span class="pln">document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'notes'</span><span class="pun">).</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">ul</span><span class="pun">)</span></pre>

<h2>
	إجراء التعديلات على DOM من الطرفية
</h2>

<p>
	يمكننا القيام بالعديد من العمليات على صفحة الويب باستخدام واجهة DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>. تدعى العقدة الأعلى في شجرة ملف HTML، كائن <code>document</code>. وللوصول إلى كائن مستند صفحة الويب من الطرفية اكتب كلمة <code>document</code> في النافذة Console.
</p>

<p style="text-align: center;">
	<img alt="console_document_015.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53634" data-unique="1s4wk05k2" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_document_015.png.95b961526f85df5d587f88f8278917ff.png">
</p>

<p>
	لنضف ملاحظة جديدة إلى الصفحة باستخدام الطرفية. دعونا نستعرض أولًا قائمة الملاحظات الموجودة في أول عنصر <code>ul</code> تحتويه الصفحة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_34" style=""><span class="pln">list </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementsByTagName</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">)[</span><span class="lit">0</span><span class="pun">]</span></pre>

<p>
	بعد ذلك سننشئ عنصر <code>li</code> جديد ونكتب نصًا ما داخله:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_53" style=""><span class="pln">newElement </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">)</span><span class="pln">
newElement</span><span class="pun">.</span><span class="pln">textContent </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Page manipulation from console is easy'</span></pre>

<p>
	وأخيرًا سنضيف العنصر الجديد إلى القائمة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_36" style=""><span class="pln">list</span><span class="pun">.</span><span class="pln">appendChild</span><span class="pun">(</span><span class="pln">newElement</span><span class="pun">)</span></pre>

<p style="text-align: center;">
	<img alt="console_document_016.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53635" data-unique="7alrj1j4r" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_document_016.png.52df02c8a172b5f6cca25d65792db2f2.png">
</p>

<p>
	على الرغم من أن محتوى الصفحة قد تغير على متصفحك، إلا أنَّ هذا التغيير مؤقت. فلو حاولت إعادة تحميل الصفحة ستختفي التغيرات التي أجريتها، ذلك أن التغيرات لم ترفع إلى الخادم. إذًا، ستنشئ شيفرة JavaScript التي أحضرها المتصفح، قائمة بالملاحظات الموجودة فقط في العنوان <a href="https://fullstack-exampleapp.herokuapp.com/data.json" ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/data.json</a>
</p>

<h2>
	صفحات الأنماط الانسيابية Cascading Style Sheets CSS
</h2>

<p>
	يحتوي عنصر <code>head</code> في ملف HTML المرتبط بالصفحة Notes، عنصر ارتباط <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link" rel="external nofollow">Link</a>، يخبر المتصفح ضرورة إحضار ملف <a href="https://https://wiki.hsoub.com/CSS" rel="external nofollow">CSS</a> من العنوان <a href="https://fullstack-exampleapp.herokuapp.com/main.css" rel="external nofollow">main.css</a>. وتعتبر ملفات CSS لغة وصفية (Markup) تستخدم بكثرة في التحكم بمظهر صفحات الويب.
</p>

<p>
	يظهر ملف CSS الذي سيحضره المتصفح كالتالي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_5805_16" style=""><span class="pun">.</span><span class="pln">container </span><span class="pun">{</span><span class="pln">
  padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">10px</span><span class="pun">;</span><span class="pln">
  border</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1px</span><span class="pln"> solid</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">notes </span><span class="pun">{</span><span class="pln">
  color</span><span class="pun">:</span><span class="pln"> blue</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يعرّف الملف محددي صنف (<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors" rel="external nofollow">Class Selectors</a>). يستخدم محدد الصنف لاختيار أجزاء من صفحة الويب، يطبق عليها قواعد محددة للتحكم بمظهرها. يبدأ سطر تعريف محدد الصنف بنقطة (.)، يليها اسم لهذا الصنف. وتعتبر هذه الأصناف (خاصيات <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class" rel="external nofollow">attributes</a>) يمكن إضافتها إلى عناصر HTML للتحكم بمظهر هذه العناصر.
</p>

<p>
	يمكن تفحص خاصيات CSS ضمن نافذة Elements في الطرفية:
</p>

<p style="text-align: center;">
	<img alt="console_elements_css_017.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53637" data-unique="zih7px2ii" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_elements_css_017.png.0c48bdf9d81a865b9ae1f15154e2ef8d.png">]
</p>

<p>
	لاحظ أن العنصر <code>div</code> يمتلك الصنف container، بينما يمتلك العنصر <code>ul</code> الصنف notes. وبالعودة إلى ملف CSS، فإن أي عنصر يمتلك الصنف container سيُحاط بمربع مستمر سماكته 1 بكسل وسيُضبط بعد العنصر عن محيطه (padding) بمقدار 10 بكسل، وأي عنصر يمتلك الصنف notes سيكون النص فيه أزرق اللون.
</p>

<p>
	يمكن لعناصر HTML امتلاك خاصيات أخرى غير <code>classes</code>. فالعنصر <code>div</code> الذي يحتوي الملاحظات notes، يمتلك خاصية تدعى<code>id</code>. تستخدم JavaScript هذه الخاصية لإيجاد العنصر.
</p>

<p>
	يمكن استخدام النافذة Elements في الطرفية لتغيير مظهر العناصر. وكما هي الحال لن تكون التغييرات التي نجريها دائمة. إن أردت تغييرات دائمة، عليك أن تحفظها في مستند CSS الموجود على الخادم.
</p>

<p style="text-align: center;">
	<img alt="console_elements_css_change_018.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53638" data-unique="8sh14jcdq" src="https://academy.hsoub.com/uploads/monthly_2020_11/console_elements_css_change_018.png.60dd1f485de3ab3d75f9729990803b5d.png">
</p>

<h2>
	تحميل صفحة تحتوي على شيفرة JavaScript (نظرة ثانية)
</h2>

<p>
	دعونا نعيد النظر إلى ما يجري عندما نفتح الصفحة <a href="https://fullstack-exampleapp.herokuapp.com/notes" ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/notes</a> من خلال المتصفح.
</p>

<ul>
	<li>
		<p>
			يحضر المتصفح شيفرة HTML التي تحدد هيكل ومحتوى الصفحة من الخادم عبر طلب HTTP-GET.
		</p>
	</li>
	<li>
		<p>
			تطلب العناصر <code>link</code> في شيفرة HTML من المتصفح إحضار ملف CSS عنوانه main.css وكذلك ملف JavaScript عنوانه main.js من الخادم.
		</p>
	</li>
	<li>
		<p>
			ينفذ المتصفح شيفرة JavaScript.
		</p>
	</li>
	<li>
		<p>
			ترسل الشيفرة طلب HTTP-GET إلى العنوان <a href="https://fullstackexampleapp.herokuapp.com/data.json" ipsnoembed="false" rel="external nofollow">https://fullstackexampleapp.herokuapp.com/data.json</a> الذي سيستجيب بإرسال الملاحظات على شكل بيانات JSON.
		</p>
	</li>
	<li>
		<p>
			عندما تصل البيانات، سينفذ المتصفح الشيفرة الموجودة ضمن معالج حدث، وهذا الأخير سيظهر الملاحظات على صفحة الويب مستخدمًا الواجهة DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>.
		</p>
	</li>
</ul>

<p style="text-align: center;">
	<img alt="follow_diagram_requests_019.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53660" data-unique="h2pmd5sil" src="https://academy.hsoub.com/uploads/monthly_2020_11/follow_diagram_requests_019.png.ef80f9256a86c26190495cf2964808a7.png">
</p>

<h2>
	الاستمارات Forms وطلبات HTTP-POST
</h2>

<p>
	دعونا نتفحص الآن كيف أُضيفت ملاحظة جديدة. تحتوي الصفحة Notes على عنصر استمارة <code>Form</code>، عندما ننقر على الزر الموجود في الاستمارة، سيرسل المتصفح المعلومات التي أدخلها المستخدم إلى الخادم.
</p>

<p style="text-align: center;">
	<img alt="form_020.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53643" data-unique="uk85c9rjk" src="https://academy.hsoub.com/uploads/monthly_2020_11/form_020.png.030b1da23a13997670be1ff14d7fdc5e.png">
</p>

<p>
	لنفتح النافذة Network ولنرى كيف يتم إرسال الاستمارة:
</p>

<p style="text-align: center;">
	<img alt="form_send_021.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53645" data-unique="qvh06ufnv" src="https://academy.hsoub.com/uploads/monthly_2020_11/form_send_021.png.1daecc6146e52f6e1c0968f986cee885.png">
</p>

<p>
	نتج عن إرسال الاستمارة خمس طلبات HTTP. يمثل الأول حدث إرسال الاستمارة (Form Submit Event)، وهو طلب HTTP-POST إلى العنوان new_note الموجود على الخادم. سيستجيب الخادم برمز حالة رقمه 302، ويعني هذا أن عملية تحويل عنوان (URL-redirect) قد تمت. في هذه العملية يطلب الخادم من المتصفح إن يرفع طلب HTTP-GET جديد إلى العنوان notes الذي نجده ضمن الموقع Location الذي يمثل جزءًا من ترويسة الاستجابة التي أرسلها الخادم. سيعيد الخادم إذًا، تحميل صفحة الملاحظات. وتسبب تلك العملية ثلاثة طلبات HTTP:
</p>

<ul>
	<li>
		<p>
			إحضار ملف CSS باسم main.css
		</p>
	</li>
	<li>
		<p>
			إحضار ملف JavaScript باسم main.js
		</p>
	</li>
	<li>
		<p>
			إحضار ملف البيانات data.json
		</p>
	</li>
</ul>

<p style="text-align: center;">
	<img alt="form_send_requests_022.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53646" data-unique="i0oarlkth" src="https://academy.hsoub.com/uploads/monthly_2020_11/form_send_requests_022.png.a55b024a95edf9945cc5e8cb7e0f991f.png">
</p>

<p>
	يمكن أن نشاهد البيانات التي أرسلت أيضًا في نافذة Network:
</p>

<p style="text-align: center;">
	<img alt="form_send_requests_network_023.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53647" data-unique="1b2g1jtzo" src="https://academy.hsoub.com/uploads/monthly_2020_11/form_send_requests_network_023.png.a6c922c0cc036eb289b931a42db3a47d.png">
</p>

<p>
	يمتلك معرّف الاستمارة<code>Form</code> خاصيتي <code>action</code> و<code>method</code> اللتان تشيرا إلى أن إرسال الاستمارة سيكون على شكل طلب HTTP-POST إلى العنوان new_notes.
</p>

<p style="text-align: center;">
	<img alt="form_attributes_024.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53644" data-unique="af8v9e5on" src="https://academy.hsoub.com/uploads/monthly_2020_11/form_attributes_024.png.a1e9f45d694f271125d0af6860031c14.png">
</p>

<p>
	تعتبر الشيفرة الموجودة على الخادم والمسؤولة عن الاستجابة إلى طلب المتصفح بسيطة (<strong>لاحظ</strong>: هذه الشيفرة موجودة على الخادم، وليست جزءًا من ملف JavaScript الذي يحضره المتصفح):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_40" style=""><span class="pln">app</span><span class="pun">.</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/new_note'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">req</span><span class="pun">,</span><span class="pln"> res</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  notes</span><span class="pun">.</span><span class="pln">push</span><span class="pun">({</span><span class="pln">
    content</span><span class="pun">:</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">.</span><span class="pln">note</span><span class="pun">,</span><span class="pln">
    date</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">(),</span><span class="pln">
  </span><span class="pun">})</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> res</span><span class="pun">.</span><span class="pln">redirect</span><span class="pun">(</span><span class="str">'/notes'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	ترسل البيانات ضمن جسم (Body) طلب الإرسال (Post-Request) حيث يتمكن الخادم عندها من الوصول إلى البيانات الموجودة في جسم كائن من النوع Request يدعى <code>req</code> باستعمال الطريقة <code>req.body</code>. ومن ثم ينشأ الخادم كائنًا جديدًا من النوع <code>note</code>، ويضيفه إلى مصفوفة تدعى <code>notes</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_42" style=""><span class="pln">notes</span><span class="pun">.</span><span class="pln">push</span><span class="pun">({</span><span class="pln">
  content</span><span class="pun">:</span><span class="pln"> req</span><span class="pun">.</span><span class="pln">body</span><span class="pun">.</span><span class="pln">note</span><span class="pun">,</span><span class="pln">
  date</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">(),</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	يضم الكائن <code>note</code> حقلين، يدعى الأول <code>content</code> يحوي نص الملاحظة، ويدعى الآخر<code>date</code> ويحوي معلومات عن تاريخ ووقت إنشاء الملاحظة. طبعًا، لم يحفظ الخادم هذه الملاحظة ضمن قاعدة بيانات، وبالتالي ستختفي الملاحظة الجديدة بانتهاء جلسة العمل.
</p>

<h2>
	تقنية AJAX
</h2>

<p>
	اعتمدت صفحة Notes في التطبيق السابق أسلوبًا قديمًا في <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8/" rel="">تطوير الويب</a>، بالإضافة إلى استخدامه تقنية AJAX التي تصدرت قائمة تقنيات الويب بداية العقد الماضي.
</p>

<p>
	تأتي التسمية <a href="https://en.wikipedia.org/wiki/Ajax_(programming)" rel="external nofollow">AJAX</a> من (Asynchronous JavaScript and XML). قدم هذا المصطلح في فبراير (شباط) عام 2005، على خلفية التطورات في تقنية المتصفح، لتقدم مقاربةً ثوريةً جديدةً تمكن المتصفح من إحضار محتوى صفحات الويب باستخدام شيفرة JavaScript مدمجة ضمن HTML، دون الحاجة لإعادة تكوين (Rerender) الصفحة من جديد.
</p>

<p>
	استخدمت جميع تطبيقات الويب أسلوب التطبيق النموذجي الذي استعرضناه سابقًا قبل ظهور Ajax. فجميع البيانات التي تعرض في الصفحة، يتم إحضارها عند تنفيذ شيفرة HTML التي أنشأها الخادم. استخدمت صفحة Note تقنية AJAX لإحضار البيانات، بينما استخدمت الطريقة التقليدية في إرسال الاستمارة. وتعكس العناوين التي استخدمها التطبيق أسلوب الزمن القديم اللامبالي، حيث أحضرت بيانات JSON من العنوان: <a href="https://fullstack-exampleapp.herokuapp.com/data.json" ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/data.json</a> وأرسلت الملاحظات الجديدة إلى العنوان: <a href="https://fullstack-exampleapp.herokuapp.com/new_note." ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/new_note.</a> لاتعتبر هذه العناوين مقبولة حاليًا، كونها لا تتقيد بالتفاهمات العامة التي جرى الاتفاق عليها بخصوص واجهة التطبيقات <a href="https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services" rel="external nofollow">RESTful</a> التي سنراها في القسم 3. شاع مصطلح AJAX كثيرًا لدرجة أنه اعتبر من المسلمات، ثم تلاشى في عالم النسان ولم يعد يسمع به أحد من الأجيال الجديدة.
</p>

<h2>
	تطبيق من صفحة واحدة
</h2>

<p>
	تسلك الصفحة الرئيسية في المثال النموذجي الذي عملنا عليه سلوك صفحة الويب التقليدية. حيث تجري العمليات المنطقية للتطبيق على الخادم، بينما يكّون المتصفح ملف HTML بمقتضى الشيفرة المكتوبة. أما صفحة Notes، فتلقي على المتصفح بعض المسؤولية في توليد شيفرة HTML لعرض الملاحظات الموجودة. إذ ينفذ شيفرة JavaScript التي أحضرها من الخادم، وستحضر هذه الشيفرة بدورها الملاحظات على شكل بيانات JSON، ثم يضيف إليها المتصفح عناصر HTML لعرض الملاحظات على الصفحة مستخدمًا DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>.
</p>

<p>
	سادت فكرة تصميم تطبيق من صفحة واحدة (<a href="https://en.wikipedia.org/wiki/Single-page_application" rel="external nofollow">Single-page application</a> (SPA، في السنوات الأخيرة. فمواقع الويب التي تستخدم هذا الأسلوب، لاتحضر صفحاتها من الخادم بشكل منفصل كما فعل التطبيق النموذجي السابق، بل تضم جميع الصفحات في صفحة HTML واحدة وتحضرها، ويتم التعامل معها لاحقًا بواسطة شيفرة JavaScript التي تُنفَّذ ضمن المتصفح.
</p>

<p>
	تحمل صفحة Notes في تطبيقنا السابق شبهًا بتطبيقات الويب ذات الصفحة الواحدة، لكنها لم تبلغ هذا المستوى بعد. فبالرغم من أن منطق تكوين الملاحظات ينفذه المتصفح، لاتزال الصفحة تستخدم الطريقة التقليدية في إضافة الملاحظات. حيث ترسل الاستمارة البيانات إلى الخادم، الذي يوجه المتصفح لإعادة تحميل الصفحة مع إعادة توجيه نحو عنوان جديد.
</p>

<p>
	يحوي العنوان التالي <a href="https://fullstack-exampleapp.herokuapp.com/spa" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/spa</a> نسخة الصفحة الواحدة من تطبيقنا النموذجي. حيث نلاحظ للوهلة الأولى تطابق الطريقتين. فللطريقتين شيفرة HTML نفسها، لكن ملف JavaScript مختلف ويدعى (spa.js)، وكذلك حصل تغيير بسيط في كيفية استخدام معرّف الاستمارة <code>Form</code>، فلا تمتلك الاستمارة الآن خاصيات <code>method</code> و <code>action</code> لتحدد كيف وأين سترسل البيانات المدخلة ضمنها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="53657" href="https://academy.hsoub.com/uploads/monthly_2020_11/spa_form_025.png.b5ff3e0601fb39aa7590208cabed1c11.png" rel=""><img alt="spa_form_025.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53657" data-unique="t62vd72jf" src="https://academy.hsoub.com/uploads/monthly_2020_11/spa_form_025.thumb.png.b6eb4120092790885ce79ac6b844d6a6.png"></a>
</p>

<p>
	افتح نافذة Network، وامسح محتواها بالنقر على الرمز ?. ستلاحظ أن طلبًا واحدًا فقط أرسل إلى الخادم عند إنشاء ملاحظة جديدة.
</p>

<p style="text-align: center;">
	<img alt="spa_form_request_026.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53658" data-unique="o9n22hi96" src="https://academy.hsoub.com/uploads/monthly_2020_11/spa_form_request_026.png.901f6d4d4cf4a9920840c956639da407.png">
</p>

<p>
	يتضمن طلب الإرسال POST إلى العنوان new_note_spa ملاحظة جديدة بصيغة بيانات JSON، تضم محتوى الملاحظة content وتوقيتها date:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_44" style=""><span class="pun">{</span><span class="pln">
  content</span><span class="pun">:</span><span class="pln"> </span><span class="str">"single page app does not reload the whole page"</span><span class="pun">,</span><span class="pln">
  date</span><span class="pun">:</span><span class="pln"> </span><span class="str">"2019-05-25T15:15:59.905Z"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يفهم الخادم أن البيانات الواردة إليه مكتوبة بصيغة JSON، عن طريق الخاصية Content-Type من ترويسة الطلب. ومن غير هذه الترويسة، لن يعرف المتصفح كيف يفسر البيانات بشكل صحيح.
</p>

<p style="text-align: center;">
	<img alt="spa_form_request_header_027.png" class="ipsImage ipsImage_thumbnailed" data-fileid="53659" data-unique="4gdgnj9tm" src="https://academy.hsoub.com/uploads/monthly_2020_11/spa_form_request_header_027.png.856dd627db191be42a7a284d37ed994a.png">
</p>

<p>
	يستجيب الخادم معلنًا نجاح عملية إنشاء الملاحظة الجديدة معيدًا رمز الحالة <a href="https://httpstatuses.com/201" rel="external nofollow">201</a>. لن يطلب من المتصفح هذه المرة إعادة توجيه الصفحة إلى عنوان آخر، بل يبقى المتصفح على نفس الصفحة دون أن يرسل أية طلبات HTTP أخرى.
</p>

<p>
	لاترسل نسخة SPA من التطبيق بيانات الاستمارة بالطريقة التقليدية، بل تستخدم شيفرة JavaScript التي تحضرها من الخادم. سنلقي نظرة سريعة على هذه الشيفرة، لكن ليس عليك الآن فهم تفاصيلها.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_46" style=""><span class="kwd">var</span><span class="pln"> form </span><span class="pun">=</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'notes_form'</span><span class="pun">)</span><span class="pln">
form</span><span class="pun">.</span><span class="pln">onsubmit </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  e</span><span class="pun">.</span><span class="pln">preventDefault</span><span class="pun">()</span><span class="pln">

  </span><span class="kwd">var</span><span class="pln"> note </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    content</span><span class="pun">:</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">elements</span><span class="pun">[</span><span class="lit">0</span><span class="pun">].</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
    date</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">(),</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  notes</span><span class="pun">.</span><span class="pln">push</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln">
  e</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">elements</span><span class="pun">[</span><span class="lit">0</span><span class="pun">].</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pln">
  redrawNotes</span><span class="pun">()</span><span class="pln">
  sendToServer</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تطلب التعليمة <code>('document.getElementById('notes_form</code> إحضار العنصر <code>Form</code> من الصفحة، وربطه بمعالج أحداث ليتعامل مع حدث إرسال الاستمارة. يستدعي معالج الأحداث مباشرة التابع <code>()e.preventDefault</code> لإيقاف الاستجابة الافتراضية لحدث الإرسال. هذه الاستجابة التي لانريد حصولها، هي من ترسل البيانات إلى الخادم من خلال طلب GET جديد. بعدها ينشأ معالج الأحداث ملاحظة جديدة ويضيفها إلى قائمة الملاحظات باستعمال التعليمة <code>(notes.push(note</code> ثم يعيد تكوين هذه القائمة على الصفحة ويرسل الملاحظة إلى الخادم.
</p>

<p>
	تمثل الشيفرة التالية تعليمات إرسال الملاحظة إلى الخادم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_829_48" style=""><span class="kwd">var</span><span class="pln"> sendToServer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">note</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">var</span><span class="pln"> xhttpForPost </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XMLHttpRequest</span><span class="pun">()</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">

  xhttpForPost</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">'POST'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/new_note_spa'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
  xhttpForPost</span><span class="pun">.</span><span class="pln">setRequestHeader</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'Content-type'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'application/json'</span><span class="pln">
  </span><span class="pun">)</span><span class="pln">
  xhttpForPost</span><span class="pun">.</span><span class="pln">send</span><span class="pun">(</span><span class="pln">JSON</span><span class="pun">.</span><span class="pln">stringify</span><span class="pun">(</span><span class="pln">note</span><span class="pun">))</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تحدد التعليمات السابقة طريقة إرسال البيانات على شكل طلب HTTP-POST وأنها بصيغة JSON، ومن ثم ترسل البيانات على شكل سلسلة JSON النصية.
</p>

<p>
	تتوفر شيفرة التطبيق على العنوان <a href="https://github.com/mluukkai/example_app." ipsnoembed="false" rel="external nofollow">https://github.com/mluukkai/example_app.</a> وعليك أن تتذكر أن التطبيق قد صمم لإبراز مفاهيم المنهاج فقط، وأنه اعتمد أسلوبًا ضعيفًا نسبيًا لايجب عليك اتباعه عند كتابة تطبيقاتك الخاصة. وينطبق كلامنا أيضًا على طريقة استخدام العناوين التي لا تتماشى مع معايير البرمجة الأفضل المعتمدة حاليًا.
</p>

<h2>
	مكتبات JavaScript
</h2>

<p>
	صمم التطبيق السابق بما يسمى <a href="https://medium.freecodecamp.org/is-vanilla-javascript-worth-learning-absolutely-c2c67140ac34" rel="external nofollow">vanilla Javascript</a> أي باستعمال جافاسكربت فقط، التي تستخدم DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> و JavaScript في تغيير بنية الصفحة. وبدلًا من استخدام التقنيتين السابقتين فقط، تستخدم مكتبات مختلفة تحتوي على أدوات يسهل التعامل معها مقارنة بتقنية DOM-<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>. وتعتبر <a href="https://jquery.co/" rel="external nofollow">JQuery</a> أحد أشهر هذه المكتبات.طورت المكتبة JQuery في الوقت الذي استخدمت فيه تطبيقات الويب الأسلوب التقليدي المتمثل بإنشاء الخادم لصفحة HTML، وقد حسَّن ظهورها فعالية المتصفح باستخدام JavaScript المكتوبة اعتمادًا على هذه المكتبة. يعتبر أحد أسباب نجاح JQuery توافقها مع المتصفحات المختلفة (cross-browser). حيث تعمل المكتبة أيًّا كان المتصفح أو الشركة التي أنتجته، وبالتالي انتفت الحاجة إلى حلول خاصة بكل متصفح.
</p>

<p>
	لا تُستخدَم JQuery اليوم بالشكل المتوقع، على الرغم من تطور أسلوب Vanilla JS -أي كما ذكرنا الاعتماد على جافاسكربت الصرفة- والدعم الجيد الذي تقدمه أشهر المتصفحات لوظائفها الأساسية. دفع انتشار التطبيق وحيد الصفحة بتقنيات أحدث من jQuery إلى الواجهة، حيث جذبت <a href="http://backbonejs.org/" rel="external nofollow">BackboneJS</a> الموجة الأولى من المطورين. لكن سرعان ما أصبحت <a href="https://angularjs.org/" rel="external nofollow">AngularJS</a> التي قدمتها غوغل، المعيار الفعلي لتطوير تطبيقات الويب الحديثة، بعد <a href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md#100-temporal-domination-2012-06-13" rel="external nofollow">إطلاقها</a> عام 2012. لكن شعبيتها انخفضت بعد أن صرّح فريق العمل في أكتوبر (تشرين الأول) لعام 2014، أن دعم النسخة الأولى سينتهي، وأن النسخة الثانية لن تكون متوافقة معها. لذلك لم تلق Angular بنسختيها ترحيبًا حارًا جدًا.
</p>

<p>
	تعتبر حاليًا مكتبة <a href="https://reactjs.org/" rel="external nofollow">React</a> التي أنتجها Facebook، الأكثر شعبية في مشاركة المتصفح عند تنفيذ منطق تطبيقات الويب. وسنتعلم خلال مسيرتنا في هذا المنهاج التعامل معها وكذلك التعامل مع مكتبة <a href="https://github.com/reactjs/redux" rel="external nofollow">Redux</a> التي سنستخدمها مع React بشكل متكرر. تبدو React حاليًا في موقع قوة، لكن عالم JavaScript دائم التغير. فالقادم الجديد لهذه العائلة <a href="https://vuejs.org/" rel="external nofollow">VueJS</a> يلقى اهتماما متزايدًا الآن (يمكنك الاطلاع على سلسلة "<a href="https://academy.hsoub.com/tags/%D9%85%D9%82%D8%AF%D9%85%D8%A9%20%D8%A5%D9%84%D9%89%20vuejs/" rel="">مقدمة إلى Vue.js</a>" للتعرف على هذه المكتبة الرائعة).
</p>

<h2>
	التطوير الشامل لتطبيق الويب
</h2>

<p>
	ما الذي يعنيه مصطلح «التطوير الشامل لتطبيق الويب» (<em>Full stack web development</em>)؟. هذا المصطلح الذي يردده الجميع دون معرفة فعلية بمضمونه أو على الأقل ليس هناك اتفاق على تعريف محدد له.
</p>

<p>
	تمتلك جميع تطبيقات الويب من الناحية العملية مستويين: الأول مستوى العمل مع المتصفح وهو الأقرب إلى المستخدم النهائي (End-User) ويعتبر المستوى الأعلى. والثاني هو مستوى الخادم وهو المستوى الأدنى. وتوضع أحيانًا <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قواعد البيانات </a>في مستوًى أخفض من مستوى الخادم. وبالتالي يمكننا التفكير بهندسة تطبيقات الويب على أنها مستويات متراكمة.
</p>

<p>
	يتم الحديث أحيانًا عن واجهة أمامية (<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-frontend-web-development/" rel="">frontend</a>) وعن واجهة خلفية (<span ipsnoautolink="true"><a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%AE%D9%84%D9%81%D9%8A%D8%A9-backend-web-development/" rel="">backend</a></span>). سيمثل المتصفح وشيفرة JavaScript التي ينفذها الواجهة الأمامية، بينما يمثل الخادم الواجهة الخلفية.
</p>

<p>
	يُفهم من مصطلح التطوير الشامل في سياق هذا المنهاج، أن العمل سيكون على كل المستويات سواء الواجهة الأمامية أو الخلفية، وكذلك على قواعد البيانات. وقد تعتبر البرمجيات الخاصة بالخادم ونظام تشغيله جزءًا من مستويات التطوير، لكننا لن ندخل في هذا الموضوع. سنكتب شيفرة الواجهة الخلفية بلغة JavaScript مستخدمين بيئة التشغيل <a href="https://nodejs.org/en/" rel="external nofollow">Node.js</a>. وسيمنح استخدام نفس لغة البرمجة على مستويات التطوير جميعها بعدًا جديدًا لعملية التطوير الشامل، علمًا أن هذا الأمر ليس ملزمًا.
</p>

<p>
	اعتاد المطورون على التخصص بأحد مستويي التطوير، ذلك أن التقنيات المستخدمة في المستويين مختلفة تمامًا. لكن في مضمار التطوير الشامل، لابد من وجود مطورين أكفاء في جميع المستويات بما فيها قواعد البيانات. كما ينبغي على المطورين في بعض الأحيان، امتلاك مهارات في التهيئة والإدارة لتشغيل تطبيقاتهم على منصات مختلفة كالمنصات السحابية (Cloud).
</p>

<h2>
	جافاسكربت المتعبة
</h2>

<p>
	يحمل التطوير الشامل للتطبيقات تحديات مختلفة. فأمور كثيرة تحدث معًا في أماكن مختلفة، وتنقيح المشاكل أصعب قليلًا مقارنة ب<a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8/" rel="">تطبيقات سطح المكتب</a>. فلا تتصرف JavaScript كما هو متوقع منها دائمًا (مقارنة بغيرها من اللغات)، كما أن الطريقة غير المتزامنة التي تعمل بها بيئة التشغيل ستبرز كل أنواع التحديات. المعرفة ببروتوكولHTTP ضروري جدًا لفهم الاتصال في الشبكة، وكذلك معالجة الأمور المتعلقة بقواعد البيانات وإدارة وتهيئة الخادم. لابد أيضا من امتلاك معرفة جيدة بتنسيق CSS لتقديم التطبيق بشكل لائق على الأقل. يتغير عالم JavaScript بسرعة، ولهذا الأمر حصته من التحديات. فكل الأدوات والمكتبات حتى اللغة نفسها عرضة للتطوير المستمر، حتى أن البعض سئم من التغيير المستمر، فأطلق مصطلح جافاسكربت المتعبة (أو <a href="https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4" rel="external nofollow">Javascript</a> <a href="https://auth0.com/blog/how-to-manage-javascript-fatigue/" rel="external nofollow">fatigue</a>). ستعاني من هذا التعب أنت أيضًا خلال مسيرتك في المنهاج، ولحسن حظنا، هناك طرق عدة لتسهيل الأمور، منها أننا سنبدأ بكتابة الشيفرة بدلًا من الغوص في عمليات التهيئة، والتي لا يمكننا تفاديها تمامًا، لكن سنحاول أن نتقدم خلال الأسابيع القليلة القادمة متجاوزين الأسوء في هذا الكابوس.
</p>

<h2>
	التمارين 0.1 - 0.6
</h2>

<p>
	ارفع حلول التمارين على منصة GitHub، وينبغي عليك الإشارة إلى إتمام عملية التحميل ضمن منظومة تسليم الملفات <a href="https://studies.cs.helsinki.fi/stats/courses/fullstackopen" rel="external nofollow">submission system</a>.
</p>

<p>
	يمكنك تحميل جميع التمارين في نفس المكان، أو استخدم أماكن مختلفة. اعط أسماء مناسبة للمجلدات إن رفعت التمارين التي تعود لأقسام مختلفة من المنهاج إلى نفس المكان، وأضف اسم mluukkai إلى قائمة المتعاونين، إن حمَّلت ملفاتك إلى مجلدات خاصة.
</p>

<p>
	تعتبر الطريقة التالية جيدة في تسمية المجلدات:
</p>

<pre class="ipsCode">part0
part1
     Courseinfo   
  unicafe
  anecdotes
part2
  phonebook
  countries
</pre>

<p>
	<strong>لاحظ</strong> أن لكل قسم مجلده الخاص الذي يضم مجلدات فرعية لكل تمرين (مثل تمرين unicafe في القسم1). <strong>وانتبه</strong> جيدًا لرفع كل التمارين العائدة لقسم محدد معًا، فلو رفعت تمرينًا واحدًا فقط، لن تتمكن من رفع أية تمارين أخرى تعود لنفس القسم.
</p>

<h3>
	1- التمرين 0.1 (HTML)
</h3>

<p>
	راجع أساسيات HTML بقراءة هذه <a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics" rel="external nofollow">الدورة التعليمية</a> من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة.
</p>

<h3>
	2- التمرين 0.2 (CSS)
</h3>

<p>
	راجع أساسيات CSS بقراءة هذه <a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/CSS_basics" rel="external nofollow">الدورة التعليمية</a> من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة.
</p>

<h3>
	3- التمرين 0.3 (HTML forms)
</h3>

<p>
	تعلم أساسيات استخدام استمارات HTML بقراءة هذه <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form" rel="external nofollow">الدورة التعليمية</a> من Mozilla. لاترفع هذا التمرين إلى GitHub، يكفي أن تطلع على الدورة.
</p>

<h3>
	4- التمرين 0.4 (ملاحظة جديدة new note)
</h3>

<p>
	في فقرة تحميل صفحة تحتوي على شيفرة JavaScript (نظرة ثانية)، عرضت سلسلة الأحداث الناتجة عن فتح <a href="https://fullstack-exampleapp.herokuapp.com/notes" rel="external nofollow">هذه الصفحة</a> على شكل <a href="https://www.geeksforgeeks.org/unified-modeling-language-uml-sequence-diagrams/" rel="external nofollow">مخطط تتابعي</a> أُنجز باستخدام خدمة <a href="https://www.websequencediagrams.com/" rel="external nofollow">websequencediagrams</a> كالتالي:
</p>

<pre class="ipsCode">browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/notes
server--`browser: HTML-code
browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/main.css
server--`browser: main.css
browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/main.js
server--`browser: main.js

note over browser:
browser starts executing js-code
that requests JSON data from server 
end note

browser-`server: HTTP GET https://fullstack-exampleapp.herokuapp.com/data.json
server--`browser: [{ content: "HTML is easy"، date: "2019-05-23" }، ...]

note over browser:
browser executes the event handler
that renders notes to display
end note
</pre>

<p>
	<strong>أنشئ مخططًا مماثلًا</strong> لتوضيح الحالة التي ينشأ فيها المستخدم ملاحظة جديدة في الصفحة <a href="https://fullstack-exampleapp.herokuapp.com/notes%D8%8C" ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/notes،</a> وذلك بكتابة شيء ما في حقل النص ونقر زر إرسال.
</p>

<p>
	يمكنك إظهار العمليات على المخدم أو المتصفح كتعليقات على المخطط، إن وجدت هذا ضروريًا. ولا حاجة أن يكون المخطط تتابعيًّا، فلا بأس بأية طريقة مفهومة لعرض الموضوع.
</p>

<p>
	ستجد كل المعلومات المتعلقة بحل هذا التمرين مع التمرينين القادمين في نص <a href="https://fullstackopen.com/en/part0/fundamentals_of_web_apps#forms-and-http-post" rel="external nofollow">هذا القسم</a>. فكرة هذه التمارين قراءة النص مرة أخرى والتفكر مليًا بما يحدث. ليس من الضروري قراءة <a href="https://github.com/mluukkai/example_app" rel="external nofollow">شيفرة</a> التطبيق على الرغم من أن ذلك ممكن.
</p>

<h3>
	5- تمرن 0.5 (تطبيق من صفحة واحدة SPA)
</h3>

<p>
	<strong>أنشئ مخططًا</strong> لتوضيح الحالة التي ينتقل فيها المستخدم إلى صفحة نسخة تطبيق من صفحة واحدة من تطبيق الملاحظات على الرابط <a href="https://fullstack-exampleapp.herokuapp.com/spa." ipsnoembed="false" rel="external nofollow">https://fullstack-exampleapp.herokuapp.com/spa.</a>
</p>

<h3>
	6- تمرين 0.6 (ملاحظة جديدة new note)
</h3>

<p>
	<strong>أنشئ مخططًا</strong> لتوضيح الحالة التي ينشئ فيها المستخدم ملاحظة جديدة مستخدمًا نسخة التطبيق ذو الصفحة الواحدة.
</p>

<p>
	بهذا التمرين نصل إلى نهاية القسم. لقد حان الوقت لترفع إجاباتك على GitHub. لا تنسى أن تشير إلى إتمام عملية التحميل ضمن منظومة تسليم الملفات <a href="https://studies.cs.helsinki.fi/stats/courses/fullstackopen" rel="external nofollow">submission system</a>.
</p>

<p>
	يمكنك <a href="https://github.com/fullstack-hy2020/fullstack-hy2020.github.io/edit/source/src/content/0/en/part0b.md" rel="external nofollow">اقتراح تعديلات على القسم</a> أيضًا إن أحببت في المقال الأصلي.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://fullstackopen.com/en/part0/fundamentals_of_web_apps#single-page-app" rel="external nofollow">Fundamentals of web apps</a> من سلسلة <a href="https://fullstackopen.com/en/" rel="external nofollow">Deep Dive Into Modern Web Development</a>
</p>
]]></description><guid isPermaLink="false">1071</guid><pubDate>Wed, 11 Nov 2020 13:00:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x627;&#x644;&#x62A;&#x62D;&#x631;&#x64A;&#x643; &#x641;&#x64A; React Native</title><link>https://academy.hsoub.com/programming/javascript/react/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D8%B1%D9%8A%D9%83-%D9%81%D9%8A-react-native-r925/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/5ef1f7251f7b7_----React-Native.jpg.3f90d6aca17b6b9f691107c310a320b1.jpg" /></p>

<p>
	يعد التحريك باستخدام مكتبة React Native من المواضيع الأساسية المطروحة في أقسام الدراسة أو ورشات العمل، ربما لكون عدد من المطورين يجدون تحديًا في استخدامها. في الوقت الذي تركّز فيه الكثير من المدونات والمصادر في الويب على جوانب الأداء عند استخدام React Native، لا يخوض إلا عدد قليل منها في الأساسيات. سنعرض في هذه المقالة لأساسيّات تطبيق التحريكات باستخدام مكتبة React Native.
</p>

<p>
	أولًا سنلقي نظرة على خلفية المكتبة وتاريخها.
</p>

<h2>
	بداية التحريكات في React Native وتطوّرها
</h2>

<p>
	عند تشغيل برنامج عابر للمنصّات مكتوب بلغة جافاسكريبت تحتاج مكوّنات React Native على هاتفك إلى تبادل المعلومات بواسطة عنصر يسمّى الجسر (Bridge). التبادل عبر هذا العنصر غير متزامن (Asynchronous)، وهو ما يجعل التطبيقات المبنية على إطار العمل React Native تصبح بطيئة لأن الطلبات غير المتزامنة المارّة على الجسر تسدّ المسار أمام شفرة جافاسكريبت التي تتفاعل مع أجزاء إطار العمل.
</p>

<p>
	للحصول على أداء عال يجب أن تصيّر (Render) التحريكات على خيط (Thread) واجهة المستخدم الأصلي في نظام التشغيل، وبما أن البيانات تحتاج للسَّلسَلة (Serialization) عبر الجسر فإن ذلك يؤدّي غالبًا إلى منع خيط جافاسكريبت، ممّا يتسبّب في نقص عدد الإطارات (Frame) على الشاشة. بقي هذا المشكل حاضرًا منذ 2015 حين كانت التحريكات تمثّل واحدة من العقبات الكبرى أمام إطار العمل React Native.
</p>

<p>
	لحسن الحظ، تحسّنت الحالة منذ ذلك الوقت بفضل الدعم الكبير من أعضاء مجتمع المطورين، إذ أصبح من الشائع الآن إنجاز 60 إطارًا في الثانية الواحدة (Frame per second, FPS) في عمليات التحريك ضمن React Native. سهّلت واجهات تطبيقات برمجيّة تصريحيّة (Declarative <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) مثل <a href="https://facebook.github.io/react-native/docs/animations.html#animated-api" rel="external nofollow">Animated</a> عمليّة تنفيذ التحريكات التفاعلية.
</p>

<h2>
	استخدام واجهة التطبيقات البرمجية Animated لتحسين الأداء
</h2>

<p>
	يواجه المطورون حتى الآن <a href="https://www.simform.com/react-native-app-performance/" rel="external nofollow">العديد من القضايا المتعلقة بالأداء</a> خاصة عندما يعملون على رسومات متحركة معقّدة.
</p>

<p>
	كما ذكرنا سابقًا، تتسبب الاختناقات في الأداء التي تحدث عند تنفيذ الرسوم في React Native، بأعباء عمل كبيرة على خيوط جافاسكربت (JavaScript threads)، مما يقلّل من معدل إظهار الإطارات، وبالتالي يتسبّب في البطء عند استخدام البرنامج، وللتغلب على هذه المشكلة نحتاج إلى الحفاظ على معدل 60 إطارًا في الثانية الواحدة.
</p>

<p>
	إن أفضل حل للحفاظ على معدّل الإطارات بالثانية هو استخدام <a href="https://facebook.github.io/react-native/docs/animations.html" rel="external nofollow">Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> لأنها تحسّن الزمن المطلوب للسَّلسَلة وعكسها (Serialization/Deserialization). تعمل Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> عبر استخدام واجهة تطبيقات تصريحية لوصف التحريكات. الفكرة التي تقوم عليها هي التصريح بالتحريك كاملًا مرةً واحدة مقدّمًا لكي تُمكِن سَلسَلة التصريح في جافاسكريبت وإرسالها إلى الجسر. ينفّذ مشغّلٌ (Driver) التحريكاتِ إطارًا بعد الآخر.
</p>

<h2>
	تنفيد التحريكات ضمن React Native
</h2>

<p>
	توجد طرق عدة لتطبيق التحريك في React Native. في ما يلي الطرق التي أجد أن لديها فائدة أكبر.
</p>

<h3>
	القيم المتحرّكة Animated values
</h3>

<p>
	يتربّع تحريك القيم على قائمتي بوصفه لبنة أساسيّة للتحريكات في تطبيقات React. تشير هذه القيم عمومًا إلى قيم حقيقة تُحوَّل إلى أعداد حقيقية عند تمريرها مع مكوّن مُحرَّك.
</p>

<p>
	فلننظر إلى المثال التالي.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_6" style="">
<span class="typ">Animated</span><span class="pun">.</span><span class="pln">timing</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">valueToAnimate</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    toValue</span><span class="pun">:</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    duration</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">start</span><span class="pun">()</span></pre>

<p>
	نلاحظ في المثال السابق أننا أسندنا القيمة 42 إلى <code>value.ToAnimate</code> والتي ستنفّذ بعد 1000 ميلي ثانية.
</p>

<p>
	كما يمكن التصريح عن قيم خاصيات التحريك الأخرى مثل الشفافية <code>opacity</code> أو الموضع <code>position</code>. في ما يلي مثال تطبيقي على الشفافية بقيم متحرّكة.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_8" style="">
<span class="pun">&lt;</span><span class="typ">Animated</span><span class="pun">.</span><span class="typ">View</span><span class="pln"> style</span><span class="pun">={{</span><span class="pln"> opacity</span><span class="pun">:</span><span class="pln"> myAnimatedOpacity </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">  </span></pre>

<h3>
	مشغلات التحريك: Animated.timing و Animated.event و Animated.decay
</h3>

<p>
	انظر إلى المشغّلات على أنها عُقد في مخطّط بياني (Graph) تغيّر قيمةً متحرّكة مع كل إطار. على سبيل المثال، ستزداد القيمة المسندة إلى <code>Animated.timing</code>، بينما ستنقص القيمة المسندة إلى <code>Animated.decay</code> في كل إطار. لنلق نظرة على المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_10" style="">
<span class="typ">Animated</span><span class="pun">.</span><span class="pln">decay</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">valueToAnimate</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   velocity</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.0</span><span class="pun">,</span><span class="pln">
   deceleration</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.9</span><span class="pln">
</span><span class="pun">}).</span><span class="pln">start</span><span class="pun">();</span></pre>

<p>
	في هذا المثال، ستنفَّذ الرسوم المتحركة انطلاقًا من سرعة محددة بالقيمة <code>2.0</code>، ثم تتناقص تدريجيًا خلال الوقت المحدَّد. أصبحت هذه الطريقة شائعة في التطبيقات العابرة للمنصّات مع بداية ظهور التوثيقات عن التصميم المسطّح (Material design). تبدو التحريكات بمظهر جيّد، وتوجد طرق عدّة لجعل التجربة لا تنسى.
</p>

<p>
	يمكن كذلك استخدام <code>Animated.event</code> لتشغيل قيمة عند تمرير المستخدم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_12" style="">
<span class="pun">&lt;</span><span class="typ">ScrollView</span><span class="pln"> onScroll</span><span class="pun">={</span><span class="typ">Animated</span><span class="pun">.</span><span class="pln">event</span><span class="pun">(</span><span class="pln">
  </span><span class="pun">[{</span><span class="pln">nativeEvent</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">contentOffset</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">y</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">scrollY</span><span class="pun">}}}]</span><span class="pln">
</span><span class="pun">)}</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="typ">ScrollView</span><span class="pun">&gt;</span></pre>

<p>
	في المثال السابق يُعيد <code>Animated.event</code> دالّة تعدّل قيمة الخاصيّة <code>nativeEvent.content.offset.y</code> في المكوّن <code>scrollView</code> لتأخد قيمة <code>scrollY</code> الحالية.
</p>

<p>
	عمومًا، يمكن استخدام مشغلّات التحريك مع القيم المتحركة أو مع مشغّلات أخرى.
</p>

<p>
	<strong>ملحوظة جانبية:</strong> انتبه إلى أنه عندما يحدّث المشغّل كل إطار فإن القيمة الجديدة تحدّث مباشرةً قيمة الخاصيّة <code>View</code>، وبالتالي يجب أن تكون حذرًا عند التصريح بالمتغيّرات وتنتبه إلى نطاقها أثناء استخدامها.
</p>

<h2>
	توابع التحويل Transform methods
</h2>

<p>
	تتيح لك توابع التحويل تحويل قيمة متحرّكة إلى قيمة متحرّكة جديدة. يمكنك استخدام توابع مثل <code>Animated.add()‎</code> و<code>Animated.multiply()‎</code> و<code>Animated.interpolate()‎</code> لتنفيذ عمليّات تحويل بين القيم. يمكنك تنفيذ عمليّة تحويل على أي عقدة في المخطّط البياني قيد التحريك كالتالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_14" style="">
<span class="pln">newAnimated</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">(</span><span class="lit">55</span><span class="pun">).</span><span class="pln">interpolate</span><span class="pun">(.....)</span><span class="pln"> </span><span class="com">// Transformation operation using Animated.interpolate() method</span></pre>

<h2>
	تحريك الخاصيّات
</h2>

<p>
	الخاصيّات المتحرّكة هي عقد خاصّة تربط بين القيم المتحرّكة وخاصيّة في مكوّن. تُولَّد تلك الخاصيّات عند تصيير الخاصيّة <code>Animated.view</code> وإسناد خاصيّات لها.
</p>

<p>
	فلننظر إلى الشفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_16" style="">
<span class="typ">Var</span><span class="pln"> opacity </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animated</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">(</span><span class="lit">0.7</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Animated</span><span class="pun">.</span><span class="typ">View</span><span class="pln"> style</span><span class="pun">={{</span><span class="pln"> opacity </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

<p>
	أضفنا خاصيّة متحرّكة تُحوِّل القيمة <code>0.7</code> إلى خاصية. في حال حدّث التابع تلك القيمة، سينعكس التغيير على خاصية <code>View</code>.
</p>

<p>
	تعمل التوابع الموصوفة أعلاه أساسًا بالتزامن مع الكائنات المتحرّكة (Animated objects) في React، كما أن توابع التحويل تؤدّي دورًا أساسيًّا في عمل تلك الكائنات.
</p>

<p>
	يغيّر مشغّل التحريك (<code>Animated.Timing</code> أو <code>Animated.Event</code> أو <code>Animated.Decay</code>) قيم التحريك في كل إطار ثم تُمرر النتيجة عبر أي تابع من توابع التحويل لتُخزَّن بصيغة خاصية عرض (الشفافية Opacity أو قيمة التحويل).
</p>

<p>
	يسلم مفسّر جافاسكريبت النتيجة إلى Native React حيث تُحدَّث الواجهة من خلال استدعاء التابع <code>setNativeProps</code>. في الأخير تُمرَّر الخاصيّة إلى iOS أو Android حيث يتسلم المكوّن <code>UIView</code> أو <code>Android.View</code> التحديثات.
</p>

<h3>
	تنفيذ الرسوم المتحركة باستخدام Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> و Native Driver
</h3>

<p>
	تشرف مشغلات جافاسكريبت منذ ظهور Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> على عملية تنفيذ التحريك، ولكن هذه الطريقة سببت تباطؤًا في عملية التحريك بسبب قلة عدد الإطارات المعروضة في الثانية ويعود السبب في ذلك أن العمل كله يتم في الخيط (Thread) الخاص بجافاسكريبت.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="47991" data-unique="hu48y5uzl" src="https://academy.hsoub.com/uploads/monthly_2020_06/request_animation_frame.png.01f35b246d4be1f1dd1ed326b7b68f31.png" alt="request_animation_frame.png"></p>

<p>
	لتجاوز هذه المشكلة أضيفت مشغلات خاصة بإطار العمل React Native وبالتالي أصبحت قادرة على تنفيذ عملية التحريك كاملةً، إطارًا بعد الآخر، ضمن React Native.
</p>

<p>
	عند استخدام <a href="https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html" rel="external nofollow">المشغل الخاصة بإطار العمل React native</a> مع Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> فإن ذلك يسمح بتحديث العرض مباشرة دون الحاجة إلى إعادة حساب القيم مرة أخرى في جافاسكربت.
</p>

<p>
	لاستخدام المشغّل الخاص بإطار العمل React يجب تعيين القيمة <code>true</code> إلى الخاصيّة <code>useNativeDriver</code> أثناء ضبط التحريكات.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_18" style="">
<span class="pln">useNativeDriver</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span></pre>

<h2>
	استخدام PanResponder للتعامل مع لمس الشاشة في React Native
</h2>

<p>
	يمكن لواجهة التطبيقات Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> تنفيذ غالبية الأعمال الروتينية عند عمل التحريكات في React Native، إلّا أنها محدودة في التعامل مع لمس الشاشة للتفاعل مع التحريكات، فهي غير قادرة على التجاوب مع الحركات التي تحدث خارج المكوّن <a href="https://facebook.github.io/react-native/docs/scrollview.html#docsNav" rel="external nofollow"><code>ScrollView</code></a>.
</p>

<p>
	رغم أنه يمكن تنفيذ أشياء كثيرة عن طريق مكوّن <code>ScrollView</code> بسيط، إلّا أن التطبيقات على الأجهزة الجوّالة تبقى ناقصة بدون لمس الشاشة التي يستعملها المستخدم للتفاعل مع التحريكات عن طريق التمرير أو التدوير على سبيل المثال.
</p>

<p>
	يمكن التعامل مع حركات اللمس في React Native بسلاسة باستخدام <a href="https://facebook.github.io/react-native/docs/panresponder.html" rel="external nofollow">PanResponder</a> مع Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>.
</p>

<p>
	يدمج PanResponder لمسات عدّة في حركة خاصّة، ويجعل لمسة واحدة تتجاوب مع لمسات إضافية لكي تعمل حركات اليد بسلاسة.
</p>

<p>
	افتراضيًّا، يتمثّل PanResponder في مقبض InteractionManager يمنع الأحداث العاملة على خيط جافاسكريبت من تعطيل حركات اللمس.
</p>

<h2>
	تحسين زمن التشغيل لانتقالات التصفح البطيئة
</h2>

<p>
	عادةً يحتاج أي تحريك يستدعي الانتقال من شاشة إلى أخرى في React Native إلى استخدام مكوّنات التصفّح. تُستخدَم مكوّنات التصفّح مثل <a href="https://reactnavigation.org/" rel="external nofollow">React Navigation</a> عادةً للانتقالات أثناء التصفح.
</p>

<p>
	تحدث الانتقالات أثناء التصفّح في React Native عادةً في خيوط جافاسكريبت، ممّا قد يتسبّب في انتقالات بطيئة في الأجهزة الرخيصة أو ذات الذاكرة المحدودة (أجهزة أندرويد أساسًا إذ أن الأجهزة العاملة بنظام iOS تتعامل مع الأمر بفاعلية أكبر). تحدث انتقالات التصفح البطيئة عادة عندما يحاول React Native تصيير شاشة جديدة في حين أنه ما زالت تُنفَّذ تحريكات في الخلفية.
</p>

<p>
	لتفادي حالات مثل تلك المذكورة أعلاه، يسمح مدير التفاعلات (<a href="https://facebook.github.io/react-native/docs/interactionmanager.html" rel="external nofollow">InteractionManager</a>) بجدولة الأنشطة التي تأخذ وقتًا في التنفيذ بجدولتها بعد تنفيذ تحريك أو تفاعل في خيط جافاسكريبت.
</p>

<h2>
	تحريك التخطيطات Layouts
</h2>

<p>
	تعمل واجهة التطبيقات البرمجية <a href="https://facebook.github.io/react-native/docs/layoutanimation.html" rel="external nofollow">LayoutAnimation</a> على تحريك الشاشة تلقائيًّا إلى الوضعية الموالية عندما يحدث التخطيط (Layout) الموالي. تُنفَّذ واجهة التطبيقات تلك ضمن خيط واجهة المستخدم (UI Thread) وهو ما يجعلها ذات أداء عال.
</p>

<p>
	تُطبَّق التحريكات المعدَّة عن طريق LayoutAnimation، فور استدعائها، على كل المكوّنات؛ بخلاف واجهة Animated التي يمكنك عن طريقها التحكّم في القيم المخصوصة بتحريكها. يمكن لواجهة LayoutAnimation تحريك كل شيء في التصيير القادم، لذا يجب استدعاؤها قبل استدعاء <code>setState</code>.
</p>

<p>
	يضمن إعداد تحريك للتخطيط قبل استدعاء <code>setState</code> تحريكات سلسة في خيط Native ويحول دون تأثر التحريكات بتنفيذ شفرة برمجية عند إطلاق دور <code>setState</code> أخرى (وهو ما يتسبّب - في الظروف العادية - في تهديد تحريكات تطبيقك).
</p>

<p>
	توجد طريقة أخرى لاستخدام LayoutAnimation وتتمثّل في استدعائها داخل التابع <code>WillReceiveProps</code>. استدع بكل بساطة التابع <code>LayoutAnimation.configureNext</code> مع تمرير الوسائط المناسبة لإعداد التحريك، كما هو موضَّح أدناه:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3691_20" style="">
<span class="typ">LayoutAnimation</span><span class="pun">.</span><span class="pln">configureNext</span><span class="pun">(</span><span class="pln">animationConfiguration</span><span class="pun">,</span><span class="pln"> callbackCompletionMethod</span><span class="pun">);</span><span class="pln"> 
</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln"> stateToChange</span><span class="pun">:</span><span class="pln"> newStateValue </span><span class="pun">});</span></pre>

<p>
	لا تدعم واجهة LayoutAnimation سوى خاصيّتين هما الشفافية (Opacity) وقابلية التكيّف (Scalability).
</p>

<p>
	تتعرّف الواجهة على العروض (Views) باستخدام مفاتيحها الفريدة وحساب وضعيّتها المتوقّعة. علاوة على ذلك، تحرّك تغيّرات الإطارات ما دام العرض يحتفظ بالمفتاح نفسه بين تغيّر الحالات.
</p>

<p>
	تعمل التحريكات المطبَّقة بواسطة LayoutAnimation ضمن الخيط الأصلي لواجهة المستخدم في نظام التشغيل، وهو أمر جيّد من ناحية الأداء، إلّا أنه يمثّل تحديًّا إذا دعت الحاجة لتحريك كل الخاصيّات بين حالات الإطارات.
</p>

<h2>
	خاتمة
</h2>

<p>
	لا يدخل هذا المقال في تفاصيل التحريكات في React Native ويكتفي بأمور سطحية، إلّا أن هناك قاعدة أساسية عند التعامل مع إطار العمل React Native وهي استخدام واجهة التطبيقات البرمجية Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> ما دام ذلك ممكنا. بالنسبة لحركات اللمس، استخدم PanResponder بجانب Animated <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>.
</p>

<p>
	يمكن التغلّب على الكثير من المشاكل التي تواجهها بالاستفادة من مشغّل Native driver إلى جانب واجهة Animated. إنْ استمرّت مشاكل الأداء رغم ذلك فالزم LayoutAnimation.
</p>

<p>
	ترجمة - وبتصرّف - للمقال <a href="https://opensource.com/article/18/6/getting-started-react-native-animations" rel="external nofollow">Getting started with React Native animations</a> لصاحبه Rakshit Soral.
</p>
]]></description><guid isPermaLink="false">925</guid><pubDate>Tue, 23 Jun 2020 12:42:09 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644; Airbnb &#x644;&#x62A;&#x646;&#x633;&#x64A;&#x642; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; React/JSX</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%AF%D9%84%D9%8A%D9%84-airbnb-%D9%84%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-reactjsx-r924/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/5ef1f495817a5_--Airbnb-React_JSX.jpg.310f2fc0f451386fa9aee131bc0efe4c.jpg" /></p>

<h2>
	القواعد الأساسية
</h2>

<ul>
<li>
		لا تضع إلا مكوِّن React واحدًا فقط في كل ملف.
		<ul>
<li>
				مع ذلك، يُسمح بوضع أكثر من مكوّن من الدوال عديمة الحالة (Stateless functions) في ملف واحد. استعن بقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md#ignorestateless" rel="external nofollow">react/no-multi-comp</a> في ESLint.
			</li>
		</ul>
</li>
	<li>
		استخدم دائمًا أسلوب الصياغة JSX.
	</li>
	<li>
		لا تستخدم التابع <code>React.createElement</code> إلا إذا كنت تهيئ التطبيق من ملف لا يستخدم صياغة JSX.
	</li>
</ul>
<h2>
	Class مقابل React.createClass مقابل stateless
</h2>

<ul>
<li>
		<p>
			استخدم <code>class extends React.Component</code> بدلًا من <code>React.createClass</code> إذا كانت لديك حالة أو مراجع (Refs) داخلية أو هما معًا.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_6" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Listing</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createClass</span><span class="pun">({</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">hello</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Listing</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">hello</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			أما إذا لم تكن لديك حالة داخلية أو مرجعية، فمن الأفضل استخدام الدوال العادية (وليس الدوال السهمية) بدلًا من استخدام الأصناف.
		</p>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_8" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Listing</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">hello</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// سيّئ (يُنصَح بعدم الاعتماد على استنباط اسم الدالة)</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Listing</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">({</span><span class="pln"> hello </span><span class="pun">})</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="pln">hello</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> </span><span class="typ">Listing</span><span class="pun">({</span><span class="pln"> hello </span><span class="pun">})</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="pln">hello</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الخلائط (Mixins)
</h2>

<ul>
<li>
		<a href="https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html" rel="external nofollow">تجنب استخدام الخلائط.</a>

		<ul>
<li>
				<strong>لماذا؟</strong> لأنها تنطوي على اعتمادات (Dependencies) ضمنية، كما قد تتسبب في اشتباك الأسماء، وترفع درجة التعقيد. يمكن استبدال الخلائط في معظم الحالات بطرق أفضل عبر المكوّنات (Components)، أو المكوّنات ذات المستوى العالي (Higher-order components) أو الوحدات المساعدة.
			</li>
		</ul>
</li>
</ul>
<h2>
	التسمية
</h2>

<ul>
<li>
		<strong>الامتدادات:</strong> استخدم الامتداد <code>jsx.</code> لمكوّنات React .
	</li>
	<li>
		<strong>اسم الملف:</strong> استخدم أسلوب التسمية <strong>PascalCase</strong> لأسماء الملفات. على سبيل المثال، <code>ReservationCard.jsx</code>.
	</li>
	<li>
		<strong>تسمية المراجع:</strong> استخدم أسلوب التسمية PascalCase لمكوّنات React وأسلوب camelCase لنسخ الكائنات (Instances).
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_10" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> reservationCard from </span><span class="str">'./ReservationCard'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="typ">ReservationCard</span><span class="pln"> from </span><span class="str">'./ReservationCard'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ReservationItem</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">ReservationCard</span><span class="pln"> </span><span class="pun">/&gt;;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> reservationItem </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">ReservationCard</span><span class="pln"> </span><span class="pun">/&gt;;</span></pre>

<ul>
<li>
		<strong>تسمية المكوّنات:</strong> استخدم اسم الملف كاسم للمكوّن. على سبيل المثال، <code>ReservationCard.jsx</code> ينبغي أن يكون اسم مرجعها <code>ReservationCard</code>. بالنسبة للمكوّنات الجذرية للمجلد (Root components)، استخدم <code>index.jsx</code> لاسم للملف واستخدم اسم المجلد لاسم المكوّن:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_12" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Footer</span><span class="pln"> from </span><span class="str">'./Footer/Footer'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Footer</span><span class="pln"> from </span><span class="str">'./Footer/index'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Footer</span><span class="pln"> from </span><span class="str">'./Footer'</span><span class="pun">;</span></pre>

<ul>
<li>
		<p>
			تسمية المكوّنات ذات المستوى العالي (Higher-order Componen): استخدم مزيجًا من اسم المكوّن ذي المستوى العالي واسم المكوِّن المُمرَّر ليكون قيمة الخاصيّة <code>displayName</code> في المكوّن المُولَّد.على سبيل المثال، إذا مُرّر للمكوّن ذي المستوى العالي <code>()withFoo</code> المكوّن Bar فإن الناتج ستكون قيمة الخاصيّة <code>displayName</code> لديه هي <code>withFoo(Bar)</code>.
		</p>

		<p>
			<strong>لماذا ا؟</strong> يمكن استخدام الخاصيّة<code>displayName</code> في أدوات المطوّرين أو في رسائل الخطأ، وعندما تعكس قيمتها تلك العلاقة بوضوح، فسيساعد ذلك على فهم ما يحدث.
		</p>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_14" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> withFoo</span><span class="pun">(</span><span class="typ">WrappedComponent</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="typ">WithFoo</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">WrappedComponent</span><span class="pln"> </span><span class="pun">{...</span><span class="pln">props</span><span class="pun">}</span><span class="pln"> foo </span><span class="pun">/&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> withFoo</span><span class="pun">(</span><span class="typ">WrappedComponent</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">function</span><span class="pln"> </span><span class="typ">WithFoo</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">WrappedComponent</span><span class="pln"> </span><span class="pun">{...</span><span class="pln">props</span><span class="pun">}</span><span class="pln"> foo </span><span class="pun">/&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">const</span><span class="pln"> wrappedComponentName </span><span class="pun">=</span><span class="pln"> </span><span class="typ">WrappedComponent</span><span class="pun">.</span><span class="pln">displayName
    </span><span class="pun">||</span><span class="pln"> </span><span class="typ">WrappedComponent</span><span class="pun">.</span><span class="pln">name
    </span><span class="pun">||</span><span class="pln"> </span><span class="str">'Component'</span><span class="pun">;</span><span class="pln">

  </span><span class="typ">WithFoo</span><span class="pun">.</span><span class="pln">displayName </span><span class="pun">=</span><span class="pln"> </span><span class="pun">`</span><span class="pln">withFoo</span><span class="pun">(</span><span class="pln">$</span><span class="pun">{</span><span class="pln">wrappedComponentName</span><span class="pun">})`;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">WithFoo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		<p>
			<strong>تسمية الخاصيّات (Props) :</strong> تجنب استعمال أسماء مكوّنات DOM لأغراض مختلفة. <strong>لماذا؟</strong> يتوقع المطوّرون أنّ خاصيّات مثل <code>style</code> و<code>className</code> تعني أشياء محددة. تغيير الواجهة البرمجية هذه في جزء من تطبيقك يجعل الشفرة البرمجية أقل قابلية للقراءة والصيانة، ويمكن أن يتسبب في أعطاب.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_16" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> style</span><span class="pun">=</span><span class="str">"fancy"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> className</span><span class="pun">=</span><span class="str">"fancy"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> variant</span><span class="pun">=</span><span class="str">"fancy"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	التصريح Declaration
</h2>

<ul>
<li>
		<p>
			لا تستخدم <code>displayName</code> لتسمية المكوّنات. بدلًا من ذلك، سمّ المكوّنات بمراجعها.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_18" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createClass</span><span class="pun">({</span><span class="pln">
  displayName</span><span class="pun">:</span><span class="pln"> </span><span class="str">'ReservationCard'</span><span class="pun">,</span><span class="pln">
  </span><span class="com">// stuff goes here</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ReservationCard</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	المحاذاة Alignment
</h2>

<ul>
<li>
		<p>
			اتبع الأساليب التالية للمحاذاة في صياغة JSX. استعن بقاعدتيْ <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md" rel="external nofollow">react/jsx-closing-bracket-location</a> و<a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md" rel="external nofollow">react/jsx-closing-tag-location</a> في ESLint.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_20" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> superLongParam</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln">
     anotherSuperLongParam</span><span class="pun">=</span><span class="str">"baz"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  superLongParam</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln">
  anotherSuperLongParam</span><span class="pun">=</span><span class="str">"baz"</span><span class="pln">
</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// if props fit in one line then keep it on the same line</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> bar</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// children get indented normally</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  superLongParam</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln">
  anotherSuperLongParam</span><span class="pun">=</span><span class="str">"baz"</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="typ">Quux</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="typ">Foo</span><span class="pun">&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	الاقتباس Quotes
</h2>

<ul>
<li>
		<p>
			استخدم دائمًا علامات الاقتباس المزدوجة (<code>"</code>) لخاصيّات JSX، وعلامات الاقتباس المفردة (<code>'</code>) لبقية عناصر جافاسكريبت. استعن بقاعدة <a href="https://eslint.org/docs/rules/jsx-quotes" rel="external nofollow">jsx-quotes</a> في ESLint.
		</p>

		<p>
			<strong>لماذا</strong>؟ تستخدم خاصيّات HTML عادةً علامات الاقتباس المزدوجة بدلًا من المفردة، لذا فخاصيّات JSX تتبع هذا الاصطلاح.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_22" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> bar</span><span class="pun">=</span><span class="str">'bar'</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> bar</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> style</span><span class="pun">={{</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">"20px"</span><span class="pln"> </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> style</span><span class="pun">={{</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="str">'20px'</span><span class="pln"> </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	إدراج المسافات Spacing
</h2>

<ul>
<li>
		<p>
			أضف دائمًا مسافةً واحدةً في الوسوم المنغلقة على ذاتها (Self-closing tags). استعن بالقاعدتين <a href="https://eslint.org/docs/rules/no-multi-spaces" rel="external nofollow">no-multi-spaces</a> و<a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-tag-spacing.md" rel="external nofollow">react/jsx-tag-spacing</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_24" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// سيّئ جدًّا</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">                 </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
 </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			لا تحش أقواس JSX المعقوصة بمسافات. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md" rel="external nofollow">react/jsx-curly-spacing</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_26" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> bar</span><span class="pun">={</span><span class="pln"> baz </span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> bar</span><span class="pun">={</span><span class="pln">baz</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	الخاصيات Props
</h2>

<ul>
<li>
		<p>
			استخدم دائمًا أسلوب التسمية camelCase لتسمية الخاصيّات.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_28" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  </span><span class="typ">UserName</span><span class="pun">=</span><span class="str">"hello"</span><span class="pln">
  phone_number</span><span class="pun">={</span><span class="lit">12345678</span><span class="pun">}</span><span class="pln">
</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  userName</span><span class="pun">=</span><span class="str">"hello"</span><span class="pln">
  phoneNumber</span><span class="pun">={</span><span class="lit">12345678</span><span class="pun">}</span><span class="pln">
</span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			احذف قيمة الخاصيّة عندما تكون قيمتها تساوي <code>true</code> على نحو صريح. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md" rel="external nofollow">react/jsx-boolean-value</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_30" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  hidden</span><span class="pun">={</span><span class="kwd">true</span><span class="pun">}</span><span class="pln">
</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  hidden
</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> hidden </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			أضف دومًا الخاصيّة <code>alt</code> في وسوم الصور(<code>&lt;img&gt;</code>). إذا كانت الصورة تقديمية (Presentational)، فيمكن للخاصيّة <code>alt</code> أن تكون نصًّا فارغًا وإلّا فيجب أن يحتوي الوسم <code>&lt;img&gt;</code> على الخاصيّة ‎role="presentation".
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_32" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"Me waving hello"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">""</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> role</span><span class="pun">=</span><span class="str">"presentation"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			لا تستخدم كلمات مثل "image" أو "photo " أو "picture" أو "صورة" في خاصيّات <code>alt</code> الخاصة بوسوم <code>&lt;img&gt;</code>. استعن بالقاعدة <a href="https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md" rel="external nofollow">jsx-a11y/img-redundant-alt</a>.
		</p>

		<p>
			<strong>لماذا؟</strong> تعلم برامج قراءة الشاشة أن <code>&lt;img&gt;</code> تعني صورة، لذلك لا توجد حاجة لإدراج هذه المعلومة في النص البديل (alt text).
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_34" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"صورة مني وأنا أشير بيدي للترحيب"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"hello.jpg"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"أشير بيدي للترحيب"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			لا تستخدم إلّا أدوار <a href="https://www.w3.org/TR/wai-aria/roles#role_definitions" rel="external nofollow">ARIA</a> الصالحة وغير المجردة. استعن بالقاعدة <a href="https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md" rel="external nofollow">jsx-a11y/aria-role</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_36" style="">
<span class="com">// سيّئ، ليس من أدوار ARIA</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div role</span><span class="pun">=</span><span class="str">"datepicker"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// سيّئ، دور ARIA مجرّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div role</span><span class="pun">=</span><span class="str">"range"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div role</span><span class="pun">=</span><span class="str">"button"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			لا تستخدم الخاصيّة <code>accesskey</code> على العناصر. استعن بالقاعدة <a href="https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md" rel="external nofollow">jsx-a11y/no-access-key.</a>
		</p>

		<p>
			<strong>لماذا؟</strong> تعقّد التناقضات بين اختصارات لوحة المفاتيح وأوامر لوحة المفاتيح التي يستعملها مَن يستخدمون برامج قراءة الشاشة ولوحة المفاتيح، تعقّد قابلية الوصول (Accessibility).
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_38" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div accessKey</span><span class="pun">=</span><span class="str">"h"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تجنب استخدام فهرس مصفوفة (Array index) ليكون خاصيّة <code>key</code>. استخدم معرّفًا فريدًا بدلًا من ذلك. (<a href="https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318" rel="external nofollow">لماذا</a>؟).
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_40" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">{</span><span class="pln">todos</span><span class="pun">.</span><span class="pln">map</span><span class="pun">((</span><span class="pln">todo</span><span class="pun">,</span><span class="pln"> index</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="typ">Todo</span><span class="pln">
    </span><span class="pun">{...</span><span class="pln">todo</span><span class="pun">}</span><span class="pln">
    key</span><span class="pun">={</span><span class="pln">index</span><span class="pun">}</span><span class="pln">
  </span><span class="pun">/&gt;</span><span class="pln">
</span><span class="pun">)}</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">{</span><span class="pln">todos</span><span class="pun">.</span><span class="pln">map</span><span class="pun">(</span><span class="pln">todo </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="typ">Todo</span><span class="pln">
    </span><span class="pun">{...</span><span class="pln">todo</span><span class="pun">}</span><span class="pln">
    key</span><span class="pun">={</span><span class="pln">todo</span><span class="pun">.</span><span class="pln">id</span><span class="pun">}</span><span class="pln">
  </span><span class="pun">/&gt;</span><span class="pln">
</span><span class="pun">))}</span></pre>

		<ul>
<li>
				عرّف دائمًا قيمًا افتراضيّة (<code>defaultProps</code>) للخاصيّات غير المطلوبة.
			</li>
		</ul>
<p>
			<strong>لماذا</strong>؟ تعدّ القيم الافتراضيّة وسيلة للتوثيق، وتوفيرها سيجنّب قارئ الشفرة البرمجية كثيرًا من التخمينات. علاوةً على ذلك، قد يعني تعيين القيم الافتراضية أنك تستطيع الاستغناء عن التحقق في نوع البيانات أحيانا.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_47" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> SFC</span><span class="pun">({</span><span class="pln"> foo</span><span class="pun">,</span><span class="pln"> bar</span><span class="pun">,</span><span class="pln"> children </span><span class="pun">})</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="pln">foo</span><span class="pun">}{</span><span class="pln">bar</span><span class="pun">}{</span><span class="pln">children</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
SFC</span><span class="pun">.</span><span class="pln">propTypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  foo</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">number</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">
  bar</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">,</span><span class="pln">
  children</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">node</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> SFC</span><span class="pun">({</span><span class="pln"> foo</span><span class="pun">,</span><span class="pln"> bar</span><span class="pun">,</span><span class="pln"> children </span><span class="pun">})</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="pln">foo</span><span class="pun">}{</span><span class="pln">bar</span><span class="pun">}{</span><span class="pln">children</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
SFC</span><span class="pun">.</span><span class="pln">propTypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  foo</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">number</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">
  bar</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">,</span><span class="pln">
  children</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">node</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
SFC</span><span class="pun">.</span><span class="pln">defaultProps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  bar</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
  children</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			لا تُسرف في استخدام الخاصيّات الممدَّدة (Spread props).
		</p>
	</li>
</ul>
<p>
	<strong>لماذا</strong>؟ لكي تتجنب قدر الإمكان تمرير الخاصيّات التي لا داعي لها إلى المكوّنات. بالنسبة للإصدار React v15.6.1 والإصدارت الأقدم، ستتجنب كذلك <a href="https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html" rel="external nofollow">تمرير سمات HTML غير صالحة إلى نموذج DOM</a>.
</p>

<h3>
	استثناءات:
</h3>

<ul>
<li>
		<p>
			المكوّنات ذات المستوى العالي التي تغلّف الخاصيّات وترفع الخاصيّة <code>propTypes</code> إلى أعلى النطاق (Hoist):
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_49" style="">
<span class="pln">	</span><span class="kwd">function</span><span class="pln"> HOC</span><span class="pun">(</span><span class="typ">WrappedComponent</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Proxy</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    </span><span class="typ">Proxy</span><span class="pun">.</span><span class="pln">propTypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	      text</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">,</span><span class="pln">
	      isLoading</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">bool
	    </span><span class="pun">};</span><span class="pln">
	
	    render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">WrappedComponent</span><span class="pln"> </span><span class="pun">{...</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
	    </span><span class="pun">}</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	</span><span class="pun">}</span></pre>
	</li>
	<li>
		<p>
			تمديد الكائنات بخاصيّات معروفة وواضحة يمكن أن يكون مفيدًا خصوصًا عند اختبار مكوّنات React بالتركيب <code>forEach</code> في Mocha.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_51" style="">
<span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> props </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    text</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
    isPublished</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div </span><span class="pun">{...</span><span class="pln">props</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;);</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			<strong>ملحوظة</strong>: حاول تصفية الخاصيّات التي لا داعي لها، واستخدم <a href="https://www.npmjs.com/package/prop-types-exact" rel="external nofollow">prop-types-exact</a> لمساعدتك على تجنب العلل.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_53" style="">
<span class="com">// جيّد</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> irrelevantProp</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln">relevantProps  </span><span class="pun">}</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">WrappedComponent</span><span class="pln"> </span><span class="pun">{...</span><span class="pln">relevantProps</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// سيّئ</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> irrelevantProp</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln">relevantProps  </span><span class="pun">}</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">WrappedComponent</span><span class="pln"> </span><span class="pun">{...</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	المرجعيّات Refs
</h2>

<ul>
<li>
		<p>
			استخدم دائمًا رد نداء (Callback) للمراجع (Refs). استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md" rel="external nofollow">react/no-string-refs</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_55" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  ref</span><span class="pun">=</span><span class="str">"myRef"</span><span class="pln">
</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  ref</span><span class="pun">={(</span><span class="pln">ref</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">myRef </span><span class="pun">=</span><span class="pln"> ref</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	الأقواس
</h2>

<ul>
<li>
		<p>
			ضع وسوم JSX بين أقواس إذا امتدت على أكثر من سطر واحد. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-wrap-multilines.md" rel="external nofollow">react/jsx-wrap-multilines</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_57" style="">
<span class="com">// سيّئ</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> variant</span><span class="pun">=</span><span class="str">"long body"</span><span class="pln"> foo</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">
           </span><span class="pun">&lt;</span><span class="typ">MyChild</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
         </span><span class="pun">&lt;/</span><span class="typ">MyComponent</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> variant</span><span class="pun">=</span><span class="str">"long body"</span><span class="pln"> foo</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="typ">MyChild</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="typ">MyComponent</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// جيّد، بالنسبة لسطر واحد</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">const</span><span class="pln"> body </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">hello</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pun">&gt;{</span><span class="pln">body</span><span class="pun">}&lt;/</span><span class="typ">MyComponent</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	الوسوم Tags
</h2>

<ul>
<li>
		<p>
			استخدم دائمًا الإغلاق الذاتي (Self-close) للوسوم التي لا أبناء لها. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md" rel="external nofollow">react/self-closing-comp</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_59" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> variant</span><span class="pun">=</span><span class="str">"stuff"</span><span class="pun">&gt;&lt;/</span><span class="typ">Foo</span><span class="pun">&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln"> variant</span><span class="pun">=</span><span class="str">"stuff"</span><span class="pln"> </span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			اجعل إغلاق الوسوم في سطر جديد إذا كان للمكوّن خاصيّات متعددة الأسطر. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md" rel="external nofollow">react/jsx-closing-bracket-location</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_61" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  bar</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln">
  baz</span><span class="pun">=</span><span class="str">"baz"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pln">
  bar</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln">
  baz</span><span class="pun">=</span><span class="str">"baz"</span><span class="pln">
</span><span class="pun">/&gt;</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	التوابع Methods
</h2>

<ul>
<li>
		<p>
			استخدم الدوال السهمية في المتغيرات المحلية.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_63" style="">
<span class="kwd">function</span><span class="pln"> </span><span class="typ">ItemList</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">ul</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">{</span><span class="pln">props</span><span class="pun">.</span><span class="pln">items</span><span class="pun">.</span><span class="pln">map</span><span class="pun">((</span><span class="pln">item</span><span class="pun">,</span><span class="pln"> index</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">Item</span><span class="pln">
          key</span><span class="pun">={</span><span class="pln">item</span><span class="pun">.</span><span class="pln">key</span><span class="pun">}</span><span class="pln">
          onClick</span><span class="pun">={()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> doSomethingWith</span><span class="pun">(</span><span class="pln">item</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> index</span><span class="pun">)}</span><span class="pln">
        </span><span class="pun">/&gt;</span><span class="pln">
      </span><span class="pun">))}</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">ul</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			اربط معالجات الأحداث الخاصّة بتابع التصيير (Render methode) داخل المنشئ. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md" rel="external nofollow">react/jsx-no-bind</a>.
		</p>

		<p>
			<strong>لماذا؟</strong> استدعاء <code>bind</code> في مسار التصيير (Render path) يُنشئ دالة جديدة لكل تابع تصيير.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_67" style="">
<span class="pln">	</span><span class="com">// سيّئ</span><span class="pln">
	</span><span class="kwd">class</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	  onClickDiv</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    </span><span class="com">// do stuff</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	
	  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">onClickDiv</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)}</span><span class="pln"> </span><span class="pun">/&gt;;</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	</span><span class="pun">}</span><span class="pln">
	
	</span><span class="com">// جيّد</span><span class="pln">
	</span><span class="kwd">class</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	  constructor</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    super</span><span class="pun">(</span><span class="pln">props</span><span class="pun">);</span><span class="pln">
	
	    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">onClickDiv </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">onClickDiv</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	
	  onClickDiv</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    </span><span class="com">// do stuff</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	
	  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
	    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">onClickDiv</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;;</span><span class="pln">
	  </span><span class="pun">}</span><span class="pln">
	</span><span class="pun">}</span></pre>
	</li>
	<li>
		<p>
			لا تستخدم الشرطة السفلية (_) في بداية أسماء التوابع الداخلية لمكوّنات React .
		</p>

		<p>
			<strong>لماذا؟</strong> تُستخدَم الشرطات السفلية في بداية أسماء المتغيّرات في لغات أخرى للدلالة على الخصوصية. ولكن، خلافًا لتلك اللغات، لا يوجد دعم أصيل للخصوصية في جافاسكريبت، فكل شيء فيها عام. إضافة شرطة سفلية في بداية أسماء الخاصيات، بغض النظرعن نواياك، لا يجعلها خاصة، ويجب أن تُعامَل كل الخاصيات (مسبوقة بالشرطة السفلية أو لا) على أنها عامة. انظر إلى النقاش حول <a href="https://github.com/airbnb/javascript/issues/1024" rel="external nofollow">1024#</a> و<a href="https://github.com/airbnb/javascript/issues/490" rel="external nofollow">enter link description here</a> للتعمّق.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_69" style="">
<span class="com">// سيّئ</span><span class="pln">
</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createClass</span><span class="pun">({</span><span class="pln">
  _onClickSubmit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// do stuff</span><span class="pln">
  </span><span class="pun">},</span><span class="pln">

  </span><span class="com">// other stuff</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  onClickSubmit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// do stuff</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">// other stuff</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تأكد من إرجاع قيمة في توابع التصيير. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-render-return.md" rel="external nofollow">react/require-render-return</a>.
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_71" style="">
<span class="com">// سيّئ</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">(&lt;</span><span class="pln">div </span><span class="pun">/&gt;);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// جيّد</span><span class="pln">
render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div </span><span class="pun">/&gt;);</span><span class="pln">
</span><span class="pun">}</span></pre>

		<p>
			 
		</p>
	</li>
</ul>
<h2>
	الترتيب Ordering
</h2>

<ul>
<li>
		الترتيب عند تمديد الصنف <code>React.Component</code> لإنشاء مكوّن React جديد (<code>class extends React.Component</code>):
	</li>
</ul>
<ol>
<li>
		التوابع الثابتة (<code>static</code>) الاختيارية،
	</li>
	<li>
		<code>constructor</code>
	</li>
	<li>
		<code>getChildContext</code>
	</li>
	<li>
		<code>componentWillMount</code>
	</li>
	<li>
		<code>componentDidMount</code>
	</li>
	<li>
		<code>componentWillReceiveProps</code>
	</li>
	<li>
		<code>shouldComponentUpdate</code>
	</li>
	<li>
		<code>componentWillUpdate</code>
	</li>
	<li>
		<code>componentDidUpdate</code>
	</li>
	<li>
		<code>componentWillUnmount</code>
	</li>
	<li>
		معالجات الأحداث والنقر مثل <code>‎onClickSubmit‎()‎</code> أو <code>‎onChangeDescription‎()‎</code>
	</li>
	<li>
		توابع الوصول الخاصة بـ <code>render</code> مثل <code>getSelectReason()</code>‎ أو <code>getFooterContent()</code>‎
	</li>
	<li>
		توابع <code>render</code> الاختيارية مثل <code>renderNavigation()</code>‎ أو <code>renderProfilePicture()</code>‎.
	</li>
	<li>
		<code>render</code>.
	</li>
</ol>
<ul>
<li>
		<p>
			كيفية تعريف <code>propTypes</code> و<code>defaultProps</code> و<code>contextTypes</code>
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_489_73" style="">
<span class="kwd">import</span><span class="pln"> </span><span class="typ">React</span><span class="pln"> from </span><span class="str">'react'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pln"> from </span><span class="str">'prop-types'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> propTypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  id</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">number</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">
  url</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">
  text</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> defaultProps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  text</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Hello World'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Link</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">static</span><span class="pln"> methodsAreOk</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">url</span><span class="pun">}</span><span class="pln"> data</span><span class="pun">-</span><span class="pln">id</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">id</span><span class="pun">}&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">text</span><span class="pun">}&lt;/</span><span class="pln">a</span><span class="pun">&gt;;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Link</span><span class="pun">.</span><span class="pln">propTypes </span><span class="pun">=</span><span class="pln"> propTypes</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Link</span><span class="pun">.</span><span class="pln">defaultProps </span><span class="pun">=</span><span class="pln"> defaultProps</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> </span><span class="typ">Link</span><span class="pun">;</span></pre>

		<p>
			• الترتيب الخاص بـ React.createClass. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md" rel="external nofollow">react/sort-comp</a>.
		</p>
	</li>
</ul>
<ol>
<li>
		<code>displayName</code>
	</li>
	<li>
		<code>propTypes</code>
	</li>
	<li>
		<code>contextTypes</code>
	</li>
	<li>
		<code>childContextTypes</code>
	</li>
	<li>
		<code>mixins</code>
	</li>
	<li>
		<code>statics</code>
	</li>
	<li>
		<code>defaultProps</code>
	</li>
	<li>
		<code>getDefaultProps</code>
	</li>
	<li>
		<code>getInitialState</code>
	</li>
	<li>
		<code>getChildContext</code>
	</li>
	<li>
		<code>componentWillMount</code>
	</li>
	<li>
		<code>componentDidMount</code>
	</li>
	<li>
		<code>componentWillReceiveProps</code>
	</li>
	<li>
		<code>shouldComponentUpdate</code>
	</li>
	<li>
		<code>componentWillUpdate</code>
	</li>
	<li>
		<code>componentDidUpdate</code>
	</li>
	<li>
		<code>componentWillUnmount</code>
	</li>
	<li>
		معالجات الأحداث والنقر مثل <code>‎onClickSubmit‎()‎</code> أو <code>‎onChangeDescription‎()‎</code>
	</li>
	<li>
		توابع الوصول الخاصة بـ <code>render</code> مثل <code>getSelectReason()</code>‎ أو <code>getFooterContent()</code>‎
	</li>
	<li>
		توابع <code>render</code> الاختيارية مثل <code>renderNavigation()</code>‎ أو <code>renderProfilePicture()</code>‎.
	</li>
	<li>
		<code>render</code>
	</li>
</ol>
<ul>
<li>
		<p>
			لا تستخدم <code>isMounted</code>. استعن بالقاعدة <a href="https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md" rel="external nofollow">react/no-is-mounted</a>
		</p>

		<p>
			<strong>لماذا؟</strong> استخدام <code>isMounted</code> غير مجدٍ (<a href="https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html" rel="external nofollow">Anti-pattern</a>)، وهو غير متوفر عند استخدام أصناف ES6، كما أنه سيُلغى رسميًّا قريبا.
		</p>
	</li>
</ul>
<p>
	ترجمة - وبتصرّف - للمقال <a href="https://airbnb.io/javascript/react/" rel="external nofollow">Airbnb React/JSX Style Guide</a>.
</p>
]]></description><guid isPermaLink="false">924</guid><pubDate>Tue, 23 Jun 2020 12:32:26 +0000</pubDate></item><item><title>&#x62D;&#x627;&#x644;&#x629; &#x645;&#x643;&#x648;&#x646; component state) React)</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%AD%D8%A7%D9%84%D8%A9-%D9%85%D9%83%D9%88%D9%86-component-state-react-r836/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e54e46b19139___React_8.jpg.582e96880ecee316cae0a452e77b2aac.jpg" /></p>

<p>
	سنناقش في هذا الدرس حالة المكوِّنات (component state).
</p>

<h2>
	ما هي حالة المكون (Component State)؟
</h2>

<p>
	أغلبية المكونات تأخذ الخاصيات <code>props</code> وتصيّر العنصر، لكن تتيح المكونات الحالة أيضًا، والتي يمكن أن تستخدم لتخزين معلومات حول المكوِّن التي يمكن أن تتغير مع مرور الوقت. وعادةً يأتي التغيير نتيجةً لأحداث المستخدم أو أحداث النظام (مثل رد لمدخلات المستخدم، أو طلبية للخادم بعد مرور فترة زمنية معيّنة).
</p>

<p>
	بعض الأمور التي يجب أخذها بالحسبان حول حالة مكوِّنات React:
</p>

<ol>
<li>
		إذا كان للمكوِّن حالة فيمكن ضبط الحالة الافتراضية <code>this.setState()‎</code> في الدالة البانية‎.
	</li>
	<li>
		تغيرات الحالة هي ما تجعلنا نعيد تصيير المكوِّن وجميع المكونات الفرعية التابعة له.
	</li>
	<li>
		يمكنك إعلام المكوِّن بتغيّر الحالة باستخدام <code>this.setState()</code>‎ لضبط حالةٍ جديدة.
	</li>
	<li>
		يمكن أن تدمج تغيرات الحالة البيانات الجديدة مع البيانات القديمة التي ما تزال محتواةً في الحالة (أي <code>this.state</code>).
	</li>
	<li>
		عند تغيير الحالة، فستجري عملية إعادة التصيير داخليًا، ولا يفترض بك استدعاء <code>this.render()</code>‎ مباشرةً أبدًا.
	</li>
	<li>
		يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات <code>props</code> في كائن الحالة.
	</li>
</ol>
<h2>
	العمل مع حالة المكونات
</h2>

<p>
	يتطلب التعامل مع حالة المكونات عادةً ضبط الحالة الافتراضية، والوصول إلى الحالة الحالية، وتحديث الحالة.
</p>

<p>
	سننشِئ في المثال الآتي المكوِّن <code>الذي يبيّن استخدام </code>this.state.[STATE]‎ <code>و</code>this.setState()‎. إذا ضغطتَ على المكوِّن في متصفح الويب (أي الوجه المبتسم) فستجد أنَّ المكوِّن سيبدِّل بين الحالات المتاحة (أي الأوجه المبتسمة)، وبالتالي تكون هنالك ثلاثة حالات ممكنة للمكوِّن وهي مرتبطة بالواجهة الرسومية ومعتمدة على نقرات المستخدم في واجهة المستخدم:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1457_16" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MoodComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">mood</span><span class="pun">:</span><span class="pln"> </span><span class="str">':|'</span><span class="pun">};</span><span class="pln">


  constructor</span><span class="pun">(</span><span class="pln">props</span><span class="pun">){</span><span class="pln">

</span><span class="pln">    super</span><span class="pun">(</span><span class="pln">props</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">changeMood </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">changeMood</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  changeMood</span><span class="pun">(</span><span class="pln">event</span><span class="pun">,</span><span class="pln">a</span><span class="pun">){</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">const</span><span class="pln"> moods </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">':)'</span><span class="pun">,</span><span class="str">':|'</span><span class="pun">,</span><span class="str">':('</span><span class="pun">];</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">const</span><span class="pln"> current </span><span class="pun">=</span><span class="pln"> moods</span><span class="pun">.</span><span class="pln">indexOf</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">mood</span><span class="pun">:</span><span class="pln"> current </span><span class="pun">===</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> moods</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> moods</span><span class="pun">[</span><span class="pln">current</span><span class="pun">+</span><span class="lit">1</span><span class="pun">]});</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="pln">span style</span><span class="pun">={{</span><span class="pln">fontSize</span><span class="pun">:</span><span class="str">'60'</span><span class="pun">,</span><span class="pln">border</span><span class="pun">:</span><span class="str">'1px solid #333'</span><span class="pun">,</span><span class="pln">cursor</span><span class="pun">:</span><span class="str">'pointer'</span><span class="pun">}}</span><span class="pln"> 

</span><span class="pln">          onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">changeMood</span><span class="pun">}&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">mood</span><span class="pun">}</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">)</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="pln"> </span><span class="typ">MoodComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	لاحظ أنَّ للمكوِّن <code>حالةً افتراضيةً هي :|، وهي مضبوطة باستخدام state = {mood: ':|'};</code>‎ <code>وهي تستخدم في المكوِّن عند تصييره لأول مرة عبر </code>{this.state.mood}.
</p>

<p>
	أضفنا مستمعًا للأحداث لتغيير الحالة، وهي هذه الحالة سيؤدي حدث النقر (<code>onClick</code>) على عقدة<code> إلى استدعاء الدالة </code>changeMood<code>، وداخل هذه الدالة سنستخدم </code>this.setState()<code>‎ للتبديل إلى الحالة التالية اعتمادًا على قيمة الحالة الحالية. بعد إجراء هذا التحديث (لاحظ أنَّ </code>setState()‎ ستدمج التعديلات) فسيعاد تصيير العنصر وستتغير واجهة المستخدم.
</p>

<p>
	بعض الأمور التي علينا إبقاؤها في ذهننا عند الحديث عن حالة مكوِّنات React:
</p>

<ol>
<li>
		إذا كان للمكوِّن حالة فيمكن ضبط الحالة الافتراضية الخاصية <code>state</code>‎.
	</li>
	<li>
		تغيرات الحالة هي ما تجعلنا نعيد تصيير المكوِّن وجميع المكونات الفرعية التابعة له.
	</li>
	<li>
		يمكنك إعلام المكوِّن بتغيّر الحالة باستخدام <code>this.setState()</code>‎ لضبط حالةٍ جديدة. هنالك طرائق أخرى (مثل <code>forceUpdate()</code>‎) ولكن لا يجدر بناء استخدامها إلا إذا أردنا دمج React مع مكتباتٍ من طرف ثالث.
	</li>
	<li>
		يمكن أن تدمج تغيرات الحالة البيانات الجديدة مع البيانات القديمة التي ما تزال محتواةً في الحالة (أي <code>this.state</code>). لكن هذا دمجٌ أو تحديثٌ سطحي، فلن يجرى عملية دمج عميقة.
	</li>
	<li>
		عند تغيير الحالة، فستجري عملية إعادة التصيير داخليًا، ولا يفترض بك استدعاء <code>this.render()</code>‎ مباشرةً أبدًا.
	</li>
	<li>
		يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات <code>props</code> في كائن الحالة.
	</li>
</ol>
<h2>
	الفروقات بين الحالة والخاصيات props
</h2>

<p>
	هنالك أرضيةٌ مشتركة بين الحالة <code>state</code> والخاصيات <code>props</code>:
</p>

<ol>
<li>
		كلاهما كائنات JavaScript عادية.
	</li>
	<li>
		يمكن لكليهما أن يمتلك قيمًا افتراضية.
	</li>
	<li>
		يمكن الوصول إليها باستخدام <code>this.props</code> أو <code>this.state</code>، لكن لا يجوز أن نضبط قيمهما بهذه الطريقة، إذ سيكون كلاهما للقراءة فقط عند استخدام <code>this</code>.
	</li>
</ol>
<p>
	لكنهما يستخدمان لأغراضٍ مختلفة وبطرائق مختلفة.
</p>

<p>
	الخاصيات <code>props</code>:
</p>

<ol>
<li>
		تُمرَّر الخاصيات إلى المكوِّنات من البنية الأعلى منها، سواءً كانت من مكوِّنٍ أب أو بداية المجال حيث صُيَّرت React من الأساس.
	</li>
	<li>
		الغرض من الخاصيات هو تمرير قيم الضبط إلى المكوِّن. تخيل أنها كالوسائط المُمرَّرة إلى دالة (وإن لم تكن تستعمل صيغة JSX فهذا ما تفعله تحديدًا).
	</li>
	<li>
		الخاصيات غير قابلة للتعديل في المكوِّن الذي يستقبلها، أي لا يمكننا تعديل الخاصيات المُمرَّرة إلى المكوِّن من داخل المكوِّن نفسه.
	</li>
</ol>
<p>
	الحالة (state):
</p>

<ol>
<li>
		الحالة هي تمثيلٌ للبيانات الذي سيرتبط في مرحلةٍ ما مع الواجهة الرسومية.
	</li>
	<li>
		يجب أن تبدأ الحالة دومًا بقيمةٍ افتراضية، ثم ستُعدّل الحالة داخليًا في المكوِّن باستخدام <code>setState()</code>‎.
	</li>
	<li>
		يمكن تعديل الحالة باستخدام المكوِّن الذي يحتوي عليها فقط، أي أنها خاصة.
	</li>
	<li>
		لا يفترض تعديل حالة المكوِّنات الأبناء، ويجب ألا يشارك المكوِّن حالةً قابلةً للتعديل.
	</li>
	<li>
		يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات <code>props</code> في كائن الحالة.
	</li>
</ol>
<h2>
	إنشاء مكونات عديمة الحالة (Stateless Components)
</h2>

<p>
	عندما يكون المكون نتيجةً لاستخدام الخاصيات <code>props</code> فقط دون وجود حالة <code>state</code>، فيمكن كتابة المكوِّن على شكل دالة صرفة مما يجعلنا نتفادى إنشاء نسخة من مكوِّن React. ففي المثال الآتي سيكون <code>MyComponent</code> نتيجةً لاستدعاء دالة ناتجة عن <code>React.createElement()</code>‎.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1457_8" style="">
<span class="kwd">var</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">props</span><span class="pun">){</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"doug"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	إذا ألقينا نظرةً على شيفرة JavaScript الناتجة عن عملية تحويل JSX، فستبدو الأمور جليةً وواضحةً لنا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1457_18" style="">
<span class="kwd">var</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">

</span><span class="pln">        </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">

</span><span class="pln">        </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">

</span><span class="pln">        </span><span class="str">"Hello "</span><span class="pun">,</span><span class="pln">

</span><span class="pln">        props</span><span class="pun">.</span><span class="pln">name

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MyComponent</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"doug"</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	إنشاء مكوِّن React دون اشتقاق الصنف <code>React.Component</code>‎ يشار إليه عادةً بمكوِّن عديم الحالة.
</p>

<p>
	لا يمكن تمرير خيارات الضبط إلى المكونات عديمة الحالة (مثل <code>render</code> أو <code>componentWillUnmount</code> …إلخ.)؛ لكن يمكن ضبط ‎.<code>propTypes</code> و ‎.<code>defaultProps</code> على الدالة.
</p>

<p>
	الشيفرة الآتية توضِّح مكوِّنًا عديم الحالة يستخدم ‎<code>.propTypes</code> و ‎<code>.defaultProps</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1457_12" style="">
<span class="kwd">import</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pln"> from </span><span class="str">'prop-types'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">props</span><span class="pun">){</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">MyComponent</span><span class="pun">.</span><span class="pln">defaultProps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">name</span><span class="pun">:</span><span class="str">"John Doe"</span><span class="pun">};</span><span class="pln">

</span><span class="typ">MyComponent</span><span class="pun">.</span><span class="pln">propTyes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">name</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">string</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		حاول أن تجعل أكبر عدد من المكونات عديمَ الحالة.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a href="https://www.reactenlightenment.com/react-state.html" rel="external nofollow">React Component State</a> من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
]]></description><guid isPermaLink="false">836</guid><pubDate>Wed, 04 Mar 2020 08:07:01 +0000</pubDate></item><item><title>&#x62E;&#x627;&#x635;&#x64A;&#x627;&#x62A; &#x645;&#x643;&#x648;&#x646;&#x627;&#x62A; React Component Properties) React)</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%AE%D8%A7%D8%B5%D9%8A%D8%A7%D8%AA-%D9%85%D9%83%D9%88%D9%86%D8%A7%D8%AA-react-component-properties-react-r835/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e54dbb1b9301___React_7.jpg.87b3e124c76f0ed382fe27eccf812f31.jpg" /></p>

<p>
	سنناقش في هذا الدرس استخدام خاصيات مكوِّنات React والتي تعرف بالخاصيات props.
</p>

<h2>
	ما هي خاصيات المكونات؟
</h2>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	أسهل طريقة لشرح خاصيات المكوِّنات هي القول أنَّها تسلك سلوك خاصيات HTML. بعبارةٍ أخرى، توفِّر الخاصيات خيارات الضبط للمكوِّن. فمثلًا، الشيفرة الآتية فيها المكوِّن Badge الذي يتوقع إرسال الخاصية <code>name</code> عند تهيئة المكوِّن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_9" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Tom"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">BadgeList</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	داخل دالة التصيير للمكوِّن <code>وعندما نستخدم المكوِّن</code> ستُضاف الخاصية <code>name</code> إلى المكوِّن <code>بنفس الطريقة التي نضيف فيها خاصية HTML إلى عنصر HTML (أي</code>)؛ ثم ستستخدم الخاصية <code>name</code> من المكوِّن <code>Badge</code> (عبر <code>this.props.name</code>) كعقدة نصية للعقدة التي ستصيَّر عبر المكون <code>Badge. هذا شبيهٌ بطريقة أخذ العنصر</code> في HTML الخاصية <code>value</code> التي ستُستخدَم قيمتها لعرض نص داخل حقل الإدخال.
</p>

<p>
	طريقة أخرى للتفكير في خاصيات المكوِّنات هي تخيلها كأنها قيم لخيارات الضبط المُرسَلة إلى المكوِّن. فإذا نظرتَ إلى نسخة لا تحتوي على صيغة JSX من المثال السابق فسيبدو لك جليًا أنَّ خاصيات المكوِّن ما هي إلا كائنٌ يُمرَّر إلى الخاصية <code>createElement()</code>‎ (أي <code>React.createElement(Badge, { name: "Bill" })</code>‎):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_11" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> </span><span class="com">// null لم تُعرَّف خاصيات لذا ستكون القيمة </span><span class="pln">

</span><span class="pln">      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name </span><span class="com">// كقيمة نصية this.prop.name استخدام  </span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">Badge</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">}),</span><span class="pln">

</span><span class="pln">      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">Badge</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Tom"</span><span class="pln"> </span><span class="pun">})</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">BadgeList</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	هذا شبيهٌ بطريقة ضبط الخاصيات مباشرةً على عقد React. لكن عند تمرير تعريف المكوِّن Badge إلى الدالة <code>createElement()</code>‎ بدلًا من قعدة، فستصبح الخاصيات <code>props</code> متاحةً على المكوِّن نفسه (أي <code>this.props.name</code>). تُمكِّننا خاصيات المكوِّنات من إعادة استخدام المكوِّن  مع أي اسم.
</p>

<p>
	في الشيفرة التي ألقينا إليها نظرةً في هذا القسم، لاحظنا أنَّ المكوِّن <code>BadgeList</code> يستخدم مكونَي <code>Badge</code> مع كائن <code>this.props</code> خاصٌ بكلٍ واحدٍ منها. يمكننا التأكد من ذلك بعرض قيمة <code>this.props</code> عندما يُهيَّئ المكوِّن <code>Badge</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_15" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">)}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Tom"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">BadgeList</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	نلاحظ أنَّ كل نسخة من مكوِّنات React تملك نسخةً خاصةً بها من خاصيةٍ اسمها <code>props</code> التي تكون كائن JavaScript فارغ، ثم سيُملَأ هذا الكائن عبر المكوِّن الأب باستخدام أي قيمة أو مرجعية في JavaScript، ثم ستُستخدَم هذه القيمة من المكوِّن أو تُمرَّر إلى المكونات الأبناء.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		في البيئات التي تستخدم ES5، لن نتمكن من تعديل الخاصية <code>this.props</code> لأنها كائنٌ مجمَّد (أي <code>Object.isFrozen(this.props) === true;</code>‎).
	</li>
	<li>
		يمكنك أن تعدّ <code>this.props</code> على أنها كائنٌ للقراءة فقط.
	</li>
</ul>
<h2>
	إرسال الخاصيات props إلى مكوِّن
</h2>

<p>
	تُرسَل الخاصيات إلى المكوِّن عند إضافة قيم شبيهة بخاصيات HTML إلى المكوِّن عند استخدمه وليس عند تعريفه، فمثلًا، سنجد في الشيفرة الآتية أنَّ المكوِّن Badge قد عُرِّفَ أولًا، ثم أرسلنا خاصيةً له وهي <code>name="Bill"‎</code> أثناء استخدامه (أي عند تصيير ``):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_17" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	أبقِ في ذهنك أنَّ بإمكاننا إرسال خاصية إلى المكوِّن في أي مكان يمكن أن يُستخدَم المكوِّن فيه. فعلى سبيل المثال، يبيّن المثال من القسم السابقة استخدام المكوِّن <code>Badge</code> والخاصية <code>name</code> ضمن المكوِّن <code>BadgeList</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_19" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Tom"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">BadgeList</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		يجب أن تُعدّ خاصيات المكوِّن غيرُ قابلةٍ للتعديل، ويمكن عدم تعديل الخاصيات المُرسَلة من مكوِّن آخر. فلو احتجتَ إلى تعديل قيمة خاصيات أحد المكوِّنات ثم إعادة تصييره، فلا تضبط الخاصيات باستخدام <code>this.props.[PROP] = [NEW PROP]</code>.
	</li>
</ul>
<h2>
	الحصول على خاصيات المكوِّن
</h2>

<p>
	كما ناقشنا في <a href="https://academy.hsoub.com/programming/javascript/react/%D9%85%D9%83%D9%88%D9%86%D8%A7%D8%AA-react-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-react-components-r834/" rel="">الدرس السابق</a>، يمكن الوصول إلى إلى نسخة المكوِّن من أيٍّ من خيارات الضبط التي تستعمل دالةً عبر الكلمة المحجوزة <code>this</code>. ففي المثال الآتي استخدمنا الكلمة المحجوزة <code>this</code> للوصول إلى خاصيات <code>props</code> المكوِّن <code>Badge</code> من خيار الضبط <code>render</code> بكتابة <code>this.props.name</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_22" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ليس من الصعب معرفة ما يحدث إذا ألقينا نظرةً على شيفرة JavaScript المحوَّلة من JSX:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_24" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">Badge</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Bill"</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	أُرسِل الكائن <code>{ name: "Bill"‎ }</code> إلى الدالة <code>createElement()</code>‎ إضافةً إلى مرجعيةٍ إلى المكوِّن <code>Badge</code>. القيمة <code>{ name: "Bill"‎ }</code> ستُضبَط كخاصية للمكوِّن قابلةٌ للوصول من الكائن <code>props</code>، أي أنَّ <code>this.props.name === "Bill"</code>‎.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		تذكَّر أنَّ <code>this.props</code> للقراءة فقط، ولا يجوز ضبط الخاصيات باستخدام <code>this.props.PROP = 'foo'‎</code>.
	</li>
</ul>
<h2>
	ضبط قيم افتراضية لخاصيات المكوِّن
</h2>

<p>
	يمكن ضبط الخاصيات الافتراضية عند تعريف المكوِّن باستخدام خيار الضبط <code>getDefaultProps</code>.
</p>

<p>
	المثال الآتي يبيّن كيف عرَّفنا خيار ضبط افتراضي للمكوِّن <code>Badge</code> للخاصية <code>name</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_26" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Badge</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">static</span><span class="pln"> defaultProps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    name</span><span class="pun">:</span><span class="str">'John Doe'</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">Badge</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Tom Willy"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">BadgeList</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ستُضبَط الخاصيات الافتراضية على الكائن <code>this.props</code> إذا لم تُرسَل خاصيات إلى المكوِّن. يمكنك التحقق من ذلك بملاحظة أنَّ المكوِّن <code>Badge</code> الذي لم تُضبَط الخاصية <code>name</code> فيه ستأخذ القيمة الافتراضية <code>'John Doe'</code>.
</p>

<h2>
	خاصيات المكونات هي أكثر من مجرد سلاسل نصية
</h2>

<p>
	قبل أن نلقي نظرةً على التحقق من الخاصيات، علينا أن نستوعب أولًا أنَّ خاصيات المكونات يمكن أن تكون أي قيمة صالحة في JavaScript.
</p>

<p>
	في المثال أدناه، سنضبط عدِّة خاصيات افتراضية تحتوي على مختلف قيم JavaScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_28" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">static</span><span class="pln"> defaultProps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">      propArray</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[],</span><span class="pln">

</span><span class="pln">      propBool</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      propFunc</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){},</span><span class="pln">

</span><span class="pln">      propNumber</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln">

</span><span class="pln">      propObject</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{},</span><span class="pln">

</span><span class="pln">      propString</span><span class="pun">:</span><span class="pln"> </span><span class="str">'string'</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      propArray</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">propArray</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">()}</span><span class="pln"> 

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      propFunc returns</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">propFunc</span><span class="pun">()}</span><span class="pln"> 

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;)</span><span class="pln"> </span><span class="pun">;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> propArray</span><span class="pun">={[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">]}</span><span class="pln"> propFunc</span><span class="pun">={</span><span class="kwd">function</span><span class="pun">(){</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;}}</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	لاحظ كيف أعيدت الكتابة على الخاصيتين <code>propArray</code> و <code>propObject</code> مع قيم جديدة عند إنشاء نسخة من المكوِّن <code>MyComponent</code>.
</p>

<p>
	الفكرة الرئيسية من هذا القسم هو توضيح أنَّنا لسنا محدودين بالقيم النصية عند تمرير قيم للخاصيات.
</p>

<h2>
	التحقق من خاصيات المكوِّنات
</h2>

<p>
	لاستخدامٍ سليمٍ للخاصيات ضمن المكوِّنات، يجب أن نتحقق من قيمتها عند إنشاء نسخ المكوِّنات.
</p>

<p>
	عند تعريف خيار الضبط <code>propTypes</code> يمكننا أن نضبط كيف يجب أن تكون الخاصيات وكيف نتحقق منها. سنتحقق في المثال أدناه لنرى إن كانت الخاصيتان <code>propArray</code> و <code>propObject</code> من نوع البيانات الصحيح وسنرسلها إلى المكوِّن عند تهيئته:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4494_30" style="">
<span class="kwd">import</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pln"> from </span><span class="str">'prop-types'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">static</span><span class="pln"> propTypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    propArray</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">array</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">

</span><span class="pln">    propFunc</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PropTypes</span><span class="pun">.</span><span class="pln">func</span><span class="pun">.</span><span class="pln">isRequired</span><span class="pun">,</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">




  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      propArray</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">propArray</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">()}</span><span class="pln"> 

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      propFunc returns</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">propFunc</span><span class="pun">()}</span><span class="pln"> 

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">

</span><span class="com">// لهذا المكوِّن خاصياتٌ خطأ</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> propArray</span><span class="pun">={{</span><span class="pln">test</span><span class="pun">:</span><span class="str">'test'</span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">




</span><span class="com">// لهذا المكوِّن خاصياتٌ صحيحة</span><span class="pln">

</span><span class="com">// ReactDOM.render(&lt;MyComponent propArray={[1,2]} propFunc={function(){return 3;}} /&gt;, document.getElementById('app'));</span></pre>

<p>
	لم نرسل الخاصيات الصحيحة المُحدَّدة عبر propTypes لتوضيح أنَّ فعل ذلك سيؤدي إلى حدوث خطأ. ستؤدي الشيفرة السابقة إلى ظهور رسالة الخطأ الآتية:
</p>

<pre class="ipsCode" id="ips_uid_4494_34">
Warning: Failed propType: Invalid prop `propArray` of type `object` supplied to `MyComponent`, expected `array`

Warning: Failed propType: Required prop `propFunc` was not specified in `MyComponent`.

Uncaught TypeError: this.props.propFunc is not a function
</pre>

<p>
	توفِّر React عددًا من المتحققات الداخلية (مثل PropTypes[VALIDATOR]<code>‎</code>) والتي سأشرحها بإيجاز فيما يلي، إضافةً إلى إمكانية إنشاء متحققات مخصصة.
</p>

<p>
	(انتقلت إلى مكتبة مختلفة*)
</p>

<h3>
	المتحققات الأساسية من الأنواع
</h3>

<table><tbody>
<tr>
<td>
				React.PropTypes.string
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها سلسلة نصية
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.bool
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها قيمة منطقية
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.func
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها دالة
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.number
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها عدد
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.object
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها كائن
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.array
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها مصفوفة
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.any
			</td>
			<td>
				إذا اُستخدِمَت خاصيةٌ، فتحقق أنها من أي نوع من الأنواع
			</td>
		</tr>
</tbody></table>
<h3>
	متحققات القيم المطلوبة
</h3>

<table><tbody><tr>
<td>
				React.PropTypes.[TYPE].isRequired<code>‎</code>
			</td>
			<td>
				إضافة ‎.isRequired إلى أي نوع من المتحققات سيؤدي إلى جعل الخاصية مطلوبةً (مثال ذلك propTypes:{propFunc:React.PropTypes.func.isRequired})
			</td>
		</tr></tbody></table>
<h3>
	متحققات العناصر
</h3>

<table><tbody>
<tr>
<td>
				React.PropTypes.element
			</td>
			<td>
				الخاصية هي عنصر React.
			</td>
		</tr>
<tr>
<td>
				React.PropTypes.node
			</td>
			<td>
				أي شيء يمكن تصييره: الأرقام، أو السلاسل النصية، أو العناصر، أو مصفوفة تحتوي هذه الأنواع
			</td>
		</tr>
</tbody></table>
<h3>
	المتحققات المتعددة
</h3>

<table><tbody>
<tr>
<td>
				<code>React.PropTypes.oneOf(['Mon','Fri'])‎</code>
			</td>
			<td>
				الخاصية هي أحد أنواع القيم المُحدَّدة
			</td>
		</tr>
<tr>
<td>
				<code>React.PropTypes.oneOfType([React.PropTypes.string,React.PropTypes.number])‎</code>
			</td>
			<td>
				الخاصية هي كائن يمكن أن يكون أحد أنواع القيم المُحدَّدة
			</td>
		</tr>
</tbody></table>
<h3>
	متحققات المصفوفات والكائنات
</h3>

<table><tbody>
<tr>
<td>
				<code>React.PropTypes.arrayOf(React.PropTypes.number)‎</code>
			</td>
			<td>
				الخاصية هي مصفوفة تحتوي على نوع واحد من القيم
			</td>
		</tr>
<tr>
<td>
				<code>React.PropTypes.objectOf(React.PropTypes.number)‎</code>
			</td>
			<td>
				هي كائن يحتوي على أحد أنواع القيم
			</td>
		</tr>
<tr>
<td>
				<code>React.PropTypes.instanceOf(People)‎</code>
			</td>
			<td>
				هي كائن يكون نسخةً من دالةٍ بانية معينة (كما في الكلمة المحجوزة <code>instanceof</code>)
			</td>
		</tr>
<tr>
<td>
				<code>React.PropTypes.shape({color:React.PropTypes.string,size: React.PropTypes.number})‎</code>
			</td>
			<td>
				هي كائن يحتوي على خاصيات من أنواعٍ معينة
			</td>
		</tr>
</tbody></table>
<h3>
	المتحققات المخصصة
</h3>

<table><tbody><tr>
<td>
				<code>function(props, propName, componentName){}‎</code>
			</td>
			<td>
				<p>
					توفير دالة خاصة بك للتحقق
				</p>
			</td>
		</tr></tbody></table>
<p>
	ترجمة -وبتصرف- للفصل <a href="https://www.reactenlightenment.com/react-props.html" rel="external nofollow">React Component Properties</a> من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
]]></description><guid isPermaLink="false">835</guid><pubDate>Tue, 25 Feb 2020 08:41:24 +0000</pubDate></item><item><title>&#x645;&#x643;&#x648;&#x646;&#x627;&#x62A; React &#x627;&#x644;&#x623;&#x633;&#x627;&#x633;&#x64A;&#x629; (React Components)</title><link>https://academy.hsoub.com/programming/javascript/react/%D9%85%D9%83%D9%88%D9%86%D8%A7%D8%AA-react-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-react-components-r834/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e54d53b7ea5e___React_6.jpg.d5591db593d6923c560ccda1817e9d2e.jpg" /></p>

<p>
	يبيّن هذا الدرس كيفية استخدام عقد React لإنشاء مكوِّنات React أساسية.
</p>

<h2>
	ما هي مكونات React؟
</h2>

<p>
	سنشرح في هذا القسم طبيعة مكونات React ونغطي بعض التفاصيل التي تتعلق بإنشاء مكونات React.
</p>

<p>
	عادةً تكون واجهة المستخدم (تدعى بالشجرة tree) مقسمةً إلى أقسامٍ منطقية تسمى بالفروع (branches)، وتصبح هذه الشجرة نقطة البداية للمكوِّن وكل قسم في واجهة المستخدم يصبح مكونًا فرعيًا التي يمكن بدورها أن تُقسَّم إلى مكونات فرعية؛ ويؤدي ذلك إلى <a href="https://wiki.hsoub.com/React/thinking_in_react" rel="external">تنظيم واجهة المستخدم</a> ويسمح أيضًا لتغيرات البيانات والحالات أن تمر من الشجرة إلى الفروع ومنها إلى الفروع الداخلية.
</p>

<p>
	إذا كان الشرح السابق لمكونات React مبهمًا فأقترح عليك أن تعاين واجهة المستخدم لأي تطبيق وتحاول ذهنيًا تقسيمها إلى أقسام منطقية. من المحتمل تسمية هذه الأقسام بالمكونات. مكوِّنات React هي تجريد برمجي (programmatic abstraction) لعناصر واجهة المستخدم وللأحداث ولتغيرات الحالة ولتغيرات DOM والغرض منها هو تسهيل إنشاء هذه الأقسام والأقسام الفرعية. فعلى سبيل المثال، الكثير من واجهات المستخدم للتطبيقات تحتوي على مكوِّن للتخطيط (layout) كأحد المكونات الرئيسية في واجهة المستخدم، وهذا المكون يحتوي بدوره على على مكونات فرعية مثل مكوِّن البحث ومكوِّن قائمة التنقل. ويمكن تقسيم مكوِّن البحث مثلًا إلى مكونات فرعية، فيمكن أن يكون حقل الإدخال منفصلًا عن زر البحث. وكما ترى، يمكن بسهولة أن تصبح واجهة المستخدم مكونةً من <a href="https://wiki.hsoub.com/React/thinking_in_react#.D8.A7.D9.84.D8.AE.D8.B7.D9.88.D8.A9_.D8.A7.D9.84.D8.A3.D9.88.D9.84.D9.89:_.D8.AA.D8.AC.D8.B2.D8.A6.D8.A9_.D9.88.D8.A7.D8.AC.D9.87.D8.A9_.D8.A7.D9.84.D9.85.D8.B3.D8.AA.D8.AE.D8.AF.D9.85_.D8.A5.D9.84.D9.89_.D8.AA.D8.B3.D9.84.D8.B3.D9.84_.D9.87.D8.B1.D9.85.D9.8A_.D9.85.D9.86_.D8.A7.D9.84.D9.85.D9.83.D9.88.D9.86.D8.A7.D8.AA" rel="external">شجرةٍ من المكونات</a>، وتُنشَأ العديد من واجهات المستخدم للتطبيقات حاليًا باستخدام مكونات <a href="https://ar.wikipedia.org/wiki/%D9%85%D8%A8%D8%AF%D8%A3_%D8%A7%D9%84%D9%85%D9%87%D9%85%D8%A9_%D8%A7%D9%84%D9%88%D8%A7%D8%AD%D8%AF%D8%A9" rel="external nofollow">ذاتُ غرضٍ وحيد</a>. توفِّر React الطرائق اللازمة لإنشاء هذه المكونات عبر <code>React.Component</code> إذا كنتَ تستخدم الأصناف في ES6. تقبل الدالة <code>createReactClass()</code>‎ من الحزمة <code>create-react-class</code> كائن ضبط وتُعيد نسخةً (instance) من مكوِّن React.
</p>

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

<h2>
	إنشاء مكونات React
</h2>

<p>
	يمكن إنشاء مكوِّن React الذي قد تكون له حالة state باستدعاء الدالة createReactClass()‎ من الحزمة <code>create-react-class</code> (أو اشتقاق <code>React.Component</code> إذا كنتَ تستخدم الأصناف في ES6). هذه الدالة (أو الدالة البانية) تأخذ وسيطًا واحدًا هو كائن يُستخدَم لتوفير تفاصيل المكوِّن. الجدول الآتي يبيّن خيارات الضبط المتاحة لمكوِّنات React:
</p>

<table>
<thead><tr>
<th>
				خيار الضبط
			</th>
			<th>
				الشرح
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>render</code>
			</td>
			<td>
				قيمة مطلوبة، وتُمثِّل عادةً دالةً تُعيد عقد React أو مكوِّنات React الأخرى أو القيمة <code>null</code> أو <code>false</code>.
			</td>
		</tr>
<tr>
<td>
				<code>getInitialState</code>
			</td>
			<td>
				كائن يحتوي على القيمة الابتدائية للخاصية <code>this.state</code>، يمكنك الحصول على قيمتها إذا كنت تستعمل الأصناف في ES6 عبر استخدام <code>this.state</code> في الدالة البانية.
			</td>
		</tr>
<tr>
<td>
				<code>getDefaultProps</code>
			</td>
			<td>
				كائن يحتوي على القيم التي ستُضبَط في الخاصية <code>this.props</code>، يمكنك ضبط قيمتها إذا كنت تستعمل الأصناف في ES6 باستخدام الخاصية <code>static defaultProps</code> في الصنف المشتق.
			</td>
		</tr>
<tr>
<td>
				<code>propTypes</code>
			</td>
			<td>
				كائن يحتوي على <a href="https://wiki.hsoub.com/React/typechecking_with_proptypes" rel="external">مواصفات التحقق من الخاصيات </a><a href="https://wiki.hsoub.com/React/typechecking_with_proptypes" rel="external">props</a>.
			</td>
		</tr>
<tr>
<td>
				<code>mixins</code>
			</td>
			<td>
				مصفوفة من المخاليط (mixins، وهي كائنات تحتوي على توابع [methods]) التي <a href="https://wiki.hsoub.com/React/react_without_es6#.D8.A7.D9.84.D9.85.D8.AE.D8.A7.D9.84.D9.8A.D8.B7_.28Mixins.29" rel="external">يمكن مشاركتها</a> بين المكوِّنات. لاحظ أن ES6 لا تدعم المخاليط، فلن تتمكن من استعمالها إذا كنتَ تستعمل الأصناف في ES6.
			</td>
		</tr>
<tr>
<td>
				<code>statics</code>
			</td>
			<td>
				كائن يحتوي على التوابع الساكنة (static methods).
			</td>
		</tr>
<tr>
<td>
				<code>displayName</code>
			</td>
			<td>
				سلسلة نصية تعطي اسمًا للمكوِّن، وتُستخدَم في رسائل التنقيح، وستُضبَط هذه القيمة تلقائيًا إذا كنّا نستعمل JSX.
			</td>
		</tr>
<tr>
<td>
				<code>componentWillMount</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى مرةً واحدةً تلقائيًا قبل التصيير الابتدائي مباشرةً‎.
			</td>
		</tr>
<tr>
<td>
				<code>componentDidMount</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى مرةً واحدةً تلقائيًا بعد التصيير الابتدائي مباشرةً‎.
			</td>
		</tr>
<tr>
<td>
				<code>UNSAFE_componentWillReceiveProps</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى تلقائيًا عندما يستلم المكوِّن خاصياتٍ <code>props</code> جديدة‎.
			</td>
		</tr>
<tr>
<td>
				<code>shouldComponentUpdate</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى تلقائيًا عندما يستلم المكوِّن خاصياتٍ <code>props</code> جديدة‎ أو تغيّرت حالته <code>state</code>.
			</td>
		</tr>
<tr>
<td>
				<code>UNSAFE_componentWillUpdate</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى تلقائيًا قبل أن يستلم المكوِّن خاصياتٍ <code>props</code> جديدة‎ أو تغيّرت حالته <code>state</code>.
			</td>
		</tr>
<tr>
<td>
				<code>componentDidUpdate</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى تلقائيًا بعد نقل التحديثات التي جرت على المكوِّن إلى DOM.
			</td>
		</tr>
<tr>
<td>
				<code>componentWillUnmount</code>
			</td>
			<td>
				دالة رد نداء (callback function) التي ستستدعى تلقائيًا قبل إزالة المكوِّن من شجرة DOM.
			</td>
		</tr>
</tbody>
</table>
<p>
	أهم خيارات ضبط المكوِّنات هو <code style="font-size: 16px;">render</code>، وهذا الخيار مطلوبٌ وهو دالةٌ تعيد عقد ومكونات React. وجميع خيارات ضبط المكوِّنات الأخرى اختيارية.
</p>

<p>
	الشيفرة الآتية هي مثالٌ عن إنشاء المكوِّن <code>Timer</code> من عقد React باستخدام <code>createReactClass()</code>‎ (سنستخدم الحزمة <code>create-react-class</code> في هذا المثال لترى كيف تستعمل، وسنستعمل الأصناف في ES6 لإنشاء بقية مكونات React لاحقًا).
</p>

<p>
	احرص على قراءة التعليقات في الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8287_6" style="">
<span class="kwd">var</span><span class="pln"> createReactClass </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'create-react-class'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// وتمرير كائن من خيارات الضبط Timer إنشاء المكون</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln"> 

  	 </span><span class="com">// this.state دالة تعيد كائنًا والذي سيصبح قيمة </span><span class="pln">
    getInitialState</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 

        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

            secondsElapsed</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">startTime</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

        </span><span class="pun">};</span><span class="pln">

    </span><span class="pun">},</span><span class="pln">

    tick</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تابع مخصص</span><span class="pln">

        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">

            secondsElapsed</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">secondsElapsed </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

        </span><span class="pun">});</span><span class="pln">

    </span><span class="pun">},</span><span class="pln">

    componentDidMount</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
         </span><span class="com">// دالة رد النداء لدورة حياة المكوِّن</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">interval </span><span class="pun">=</span><span class="pln"> setInterval</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">);</span><span class="pln">

    </span><span class="pun">},</span><span class="pln">

    componentWillUnmount</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
         </span><span class="com">// دالة رد النداء لدورة حياة المكوِّن</span><span class="pln">
        clearInterval</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">interval</span><span class="pun">);</span><span class="pln">

    </span><span class="pun">},</span><span class="pln">

    render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    
         </span><span class="com">// JSX باستخدام صيغة React دالة تعيد عقد</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

            </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

                </span><span class="typ">Seconds</span><span class="pln"> </span><span class="typ">Elapsed</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">secondsElapsed</span><span class="pun">}</span><span class="pln">

            </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

        </span><span class="pun">);</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> startTime</span><span class="pun">=</span><span class="str">"60"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span><span class="pln"> </span><span class="com">// startTime تمرير قيمة الخاصية </span></pre>

<p>
	تبدو الشيفرة السابقة طويلةً، لكن أغلبية الشيفرة السابقة تُنشِئ المكوِّن <timer> بتمرير كائن إلى الدالة <code>createReactClass()‎</code> لإنشاء مكوِّنٍ مع كائن ضبط يحتوي على خمس خاصيات (وهي <code>getInitialState</code> و <code>tick</code> و <code>componentDidMount</code> و <code>componentWillUnmount</code> و <code>render</code>).</timer></p>

<p>
	لاحظ أنَّ اسم المكوِّن Timer يبدأ بحرفٍ كبير، فعند إنشاء مكوِّنات React مخصصة، عليك أن تجعل أول حرفٍ من اسمها كبيرًا. أضف إلى ذلك أنَّ القيمة this ضمن خيارات الضبط تُشير إلى نسخة المكوِّن المُنشَأة. سنناقش الواجهة البرمجية للمكوِّنات بالتفصيل في نهاية هذا الدرس، لكن دعنا نتأمل خيارات الضبط المتاحة عند تعريف مكوِّن React وكيف استطعنا الإشارة إلى المكوِّن باستخدام الكلمة المحجوزة this. لاحظ أيضًا أنني أضفت في المثال السابق تابعًا خاصًا بالمكوِّن (وهو tick).
</p>

<p>
	بعد تركيب (mount) المكوِّن، فيمكننا استخدام الواجهة البرمجية التي تحتوي على أربعة توابع، وهي مبيّنة في الجدول الآتي:
</p>

<table>
<thead><tr>
<th>
				التابع
			</th>
			<th>
				مثال
			</th>
			<th>
				الشرح
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>setState()‎</code>
			</td>
			<td>
				<code>this.setState({mykey: 'my new value'});</code> <code>this.setState(function(previousState, currentProps) { return {myInteger: previousState.myInteger + 1}; });‎</code>
			</td>
			<td>
				التابع الرئيسي التي يُستخدَم لإعادة تصيير المكوِّن ومكوناته الفرعية.
			</td>
		</tr>
<tr>
<td>
				<code>ForceUpdate()‎</code>
			</td>
			<td>
				<code>this.forceUpdate(function(){//callback});‎</code>
			</td>
			<td>
				استدعاء التابع <code>forceUpdate()</code>‎ سيؤدي إلى استخدام التابع <code>render()</code>‎ دون استدعاء <code>shouldComponentUpdate()</code>‎.
			</td>
		</tr>
</tbody>
</table>
<p>
	أكثر تابع مستخدم في واجهة المكوِّنات البرمجية هو التابع setState()‎، وسيُشرَح استخدامه في درس حالة مكونات React.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		تسمى دوال رد النداء في خيارات ضبط المكوِّن (وهي <code>componentWillUnmount</code> و <code>componentDidUpdate</code> و <code>UNSAFE_componentWillUpdate</code> و <code>shouldComponentUpdate</code> و <code>UNSAFE_componentWillReceiveProps</code> و <code>componentDidMount</code> و <code>UNSAFE_componentWillMount</code>)‎ <a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">بتوابع دورة الحياة</a> (lifecycle methods) لأنَّ هذه التوابع المختلفة ستُنفَّذ في نقاط معيّنة في دورة حياة المكوِّن.
	</li>
	<li>
		الدالة <code>createReactClass</code> هي دالة تُنشِئ نسخةً من المكوِّنات وهي موجودة في الحزمة <code>create-react-class</code>.
	</li>
	<li>
		الدالة <code>render()</code>‎ هي دالة صرفة، وهذا يعني أنها لا تعدّل حالة المكوِّن، وتعيد نفس النتيجة في كل مرة تستدعى فيها، ولا تقرأ أو تكتب إلى DOM أو تتفاعل مع المتصفح (باستخدام <code>setTimout</code> على سبيل المثال). فإذا أردت التعامل مع المتصفح، فافعل ذلك في التابع <code>componentDidMount()</code>‎ أو غيره من توابع دورة الحياة. الإبقاء على الدالة <code>render()</code>‎ صرفةً يجعل التصيير عمليًا ويُسهِّل التفكير في المكوِّنات.
	</li>
</ul>
<h2>
	المكونات تعيد عقدة أو مكون واحد
</h2>

<p>
	قيمة خيار الضبط <code>render</code> التي تُعرَّف عند إنشاء المكوِّن يجب أن تعيد مكوِّن أو عقدة React واحدة فقط. هذه العقدة أو المكون يمكن أن تحتوي على أي عدد من الأبناء.
</p>

<p>
	عقدة البداية في الشيفرة الآتية يمكن أن تحتوي هذه العقدة على أي عدد من العقد الأبناء:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_11" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">reactNode</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;</span><span class="str">/span&gt; &lt;span&gt;test&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&lt;/</span><span class="pln">reactNode</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	لاحظ أننا تستطيع إعادة عقد React بجعلها على عدّة أسطر، ويمكنك أن تحيط القيمة المعادة بقوسين هلاليين (). لاحظ كيف أعدنا المكوِّن MyComponent المُعرَّف باستخدام JSX بوضعه بين قوسين:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_13" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="pln">reactNode</span><span class="pun">&gt;</span><span class="pln"> 

</span><span class="pln">          </span><span class="pun">&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">          </span><span class="pun">&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln"> 

</span><span class="pln">      </span><span class="pun">&lt;/</span><span class="pln">reactNode</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	سيحدث خطأ إذا حاولنا إعادة أكثر من عقدة React واحدة. يمكنك أن تفكر فيها مليًا، فالخطأ يحدث لأنَّ من غير الممكن إعادة دالتَي <code>React.createElement()‎</code> باستخدام JavaScript.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_15" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pln">       

</span><span class="pln">          </span><span class="pun">&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">          </span><span class="pun">&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln"> 

</span><span class="pln">      

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	ستؤدي الشيفرة السابقة إلى حدوث الخطأ الآتي:
</p>

<pre class="ipsCode">
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (8:3)




   6 |     return (

   7 |                  &lt;span&gt;test&lt;/span&gt;

\&gt;  8 |                  &lt;span&gt;test&lt;/span&gt;

     |                  ^

   9 |  );

  10 |   }

  11 | });
</pre>

<p>
	من الشائع أن نرى المطورين يضيفون عنصر حاوي لتفادي هذا الخطأ.
</p>

<p>
	هذه المشكلة تؤثر على المكوِّنات أيضًا كما تؤثر على عقد React. فلا يمكن إعادة إلا مكوِّنٍ وحيد، ولكن يمكن أن يمتلك هذا المكوِّن عددًا غير محدودٍ من الأبناء.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_18" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">MyChildComponent</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">



</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyChildComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">test</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">test</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	إذا أعدتَ مكونين متجاورين، فسيحدث نفس الخطأ:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_20" style="">
<span class="kwd">var</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">

  render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pln">        </span><span class="pun">&lt;</span><span class="typ">MyChildComponent</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">&lt;</span><span class="typ">AnotherChildComponent</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">




</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">MyChildComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">

  render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">test</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">test</span><span class="pun">&gt;;}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">




</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">AnotherChildComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">

  render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">test</span><span class="pun">&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">test</span><span class="pun">&gt;;}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<p>
	رسالة الخطأ:
</p>

<pre class="ipsCode">
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (8:2)




   6 |     return (

   7 |          &lt;MyChildComponent/&gt;

\&gt;  8 |          &lt;AnotherChildComponent/&gt;

     |          ^

   9 |  );

  10 |   }

  11 | });
</pre>

<h2>
	الإشارة إلى نسخة المكون
</h2>

<p>
	عندما يُصيّر أحد العناصر (render) فستُنشأ نسخة من مكوِّن React من الخيارات المُمرَّرة إليه، يمكننا الوصول إلى هذه النسخة (instance) وخاصياتها (مثل <code>this.props</code>) وتوابعها (مثل <code>this.setState()</code>‎) بطريقتين.
</p>

<p>
	أوّل طريقة هي استخدام الكلمة المحجوزة this داخل دالة ضبط المكوِّن. ففي المثال الآتي، جميع تعابير <code>console.log(this)</code> ستُشير إلى نسخة المكوِّن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_22" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  componentWillMount</span><span class="pun">(){</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

  componentDidMount</span><span class="pun">(){</span><span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	الطريقة الأخرى للحصول على مرجعية لنسخة المكوِّن تتضمن استخدام القيمة المُعادة من استدعاء الدالة <code>ReactDOM.render()</code>‎. بعبارةٍ أخرى، ستُعيد الدالة <code>ReactDOM.render()‎</code> مرجعيةً إلى أعلى مكوِّن جرى تصييره:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_24" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">var</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تخزين مرجعية إلى النسخة خارج دالة</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">Bar</span><span class="pun">&gt;{</span><span class="pln">foo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">}&lt;/</span><span class="typ">Bar</span><span class="pun">&gt;;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">FooInstance</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">


</span><span class="com">// Foo التأكد أنَّ القيمة المُعادة هي مرجعية إلى نسخة</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="typ">FooInstance</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> foo</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true الناتج   </span></pre>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		تُستخدَم الكلمة المحجوزة <a href="https://wiki.hsoub.com/JavaScript/this" rel="external">this</a> داخل المكوِّن للوصول إلى خصائص المكوِّن كما في <code>this.props.[NAME OF PROP]</code> و <code>this.props.children</code> و <code>this.state</code>. يمكن أن تستخدم أيضًا لاستدعاء خاصيات وتوابع الصنف التي تتشاركها جميع المكوِّنات مثل <code>this.setState</code>‎.
	</li>
</ul>
<h2>
	تعريف الأحداث في المكونات
</h2>

<p>
	يمكن إضافة الأحداث إلى عقد React داخل خيار الضبط <code>render</code> كما ناقشنا سابقًا.
</p>

<p>
	سنضبط -في المثال الآتي- حدثَي React (وهما <code>onClick</code> و <code>onMouseOver</code>) على عقد React بصيغة JSX كما لو كنّا نضبط خيارات المكوِّن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_26" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  mouseOverHandler</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you moused over'</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span><span class="pln"> </span><span class="com">// sysnthetic event instance</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  clickHandler</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you clicked'</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span><span class="pln"> </span><span class="com">// sysnthetic event instance</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">(){</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

</span><span class="pun">&lt;</span><span class="pln">div onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">clickHandler</span><span class="pun">}</span><span class="pln"> onMouseOver</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">mouseOverHandler</span><span class="pun">}&gt;</span><span class="pln">click or mouse over</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">)</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	عندما تُصيّر React مكوِّنًا فستبحث عن خاصيات ضبط الأحداث في React (مثل <code>onClick</code>)، وتعامل هذه الخاصيات معاملةً مختلفةً عن بقية الخاصيات (جميع أحداث React مذكورة في الجدول أدناه). ومن الجلي أنَّ الأحداث في شجرة DOM الحقيقية سترتبط مع معالجاتها وراء الكواليس.
</p>

<p>
	أحد جوانب هذا الارتباط هو جعل سياق دالة معالجة الحدث في نفس مجال (scope) نسخة المكوِّن. لاحظ أنَّ قيمة <code>this</code> داخل دالة معالجة الحدث ففي المثال الآتي ستُشير إلى نسخة المكوِّن نفسها.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_28" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  constructor</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    super</span><span class="pun">(</span><span class="pln">props</span><span class="pun">);</span><span class="pln">



 
</span><span class="pln">    </span><span class="com">// this هذا الربط ضروري لتعمل </span><span class="pln">

</span><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">mouseOverHandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">mouseOverHandler</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">




  mouseOverHandler</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln"> </span><span class="com">// إلى نسخة الكائن this تشير  </span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span><span class="pln"> </span><span class="com">// sysnthetic event instance</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">(){</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

      </span><span class="pun">&lt;</span><span class="pln">div onMouseOver</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">mouseOverHandler</span><span class="pun">}&gt;</span><span class="pln">mouse over me</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">)</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	تدعم React الأحداث الآتية:
</p>

<table>
<thead><tr>
<th>
				نوع الحدث
			</th>
			<th>
				الأحداث
			</th>
			<th>
				خاصيات متعلقة به
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				الحافظة
			</td>
			<td>
				<ul>
<li>
						<code>OnCopy</code> <code>onCut</code> <code>onPaste</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>DOMDataTransfer</code>
					</li>
					<li>
						<code>clipboardData</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					التركيب
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnCompositionEnd</code>
					</li>
					<li>
						<code>onCompositionStart</code>
					</li>
					<li>
						<code>onCompositionUpdate</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>data</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					لوحة المفاتيح
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnKeyDown</code>
					</li>
					<li>
						<code>onKeyPress</code>
					</li>
					<li>
						<code>onKeyUp</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>AltKey</code> <code>charCode</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)</code>
					</li>
					<li>
						<code>key</code> <code>keyCode</code> <code>locale</code>
					</li>
					<li>
						<code>location</code> <code>metaKey</code>
					</li>
					<li>
						<code>repeat</code> <code>shiftKey</code> <code>which</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					التركيز
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnChange</code> <code>onInput</code> <code>onSubmit</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>DOMEventTarget</code>
					</li>
					<li>
						<code>relatedTarget</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					النماذج
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnFocus</code> <code>onBlur</code>
					</li>
				</ul>
</td>
			<td>
				<p>
					 
				</p>
			</td>
		</tr>
<tr>
<td>
				<p>
					الفأرة
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnClick</code>
					</li>
					<li>
						<code>onContextMenu</code>
					</li>
					<li>
						<code>onDoubleClick</code>
					</li>
					<li>
						<code>onDrag</code>
					</li>
					<li>
						<code>onDragEnd</code>
					</li>
					<li>
						<code>onDragEnter</code>
					</li>
					<li>
						<code>onDragExit</code>
					</li>
					<li>
						<code>onDragLeave</code>
					</li>
					<li>
						<code>onDragOver</code>
					</li>
					<li>
						<code>onDragStart</code>
					</li>
					<li>
						<code>onDrop</code>
					</li>
					<li>
						<code>onMouseDown</code>
					</li>
					<li>
						<code>onMouseEnter</code>
					</li>
					<li>
						<code>onMouseLeave</code>
					</li>
					<li>
						<code>onMouseMove</code>
					</li>
					<li>
						<code>onMouseOut</code>
					</li>
					<li>
						<code>onMouseOver</code>
					</li>
					<li>
						<code>onMouseUp</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>AltKey</code> <code>button</code> <code>buttons</code>
					</li>
					<li>
						<code>clientX</code>
					</li>
					<li>
						<code>clientY</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)</code>
					</li>
					<li>
						<code>metaKey</code>
					</li>
					<li>
						<code>pageX</code>
					</li>
					<li>
						<code>pageY</code> <code>DOMEventTarget</code>
					</li>
					<li>
						<code>relatedTarget</code>
					</li>
					<li>
						<code>screenX</code>
					</li>
					<li>
						<code>screenY</code>
					</li>
					<li>
						<code>shiftKey</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					الاختيار
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onSelect</code>
					</li>
				</ul>
</td>
			<td>
				<p>
					 
				</p>
			</td>
		</tr>
<tr>
<td>
				<p>
					اللمس
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnTouchCancel</code> <code>onTouchEnd</code> <code>onTouchMove</code> <code>onTouchStart</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>AltKey</code> <code>DOMTouchList</code>
					</li>
					<li>
						<code>changedTouches</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)</code>
					</li>
					<li>
						<code>metaKey</code> <code>shiftKey</code>
					</li>
					<li>
						<code>DOMTouchList</code>
					</li>
					<li>
						<code>targetTouches</code>
					</li>
					<li>
						<code>DOMTouchList</code> <code>touches</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					واجهة المستخدم
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onScroll</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>Detail</code>
					</li>
					<li>
						<code>DOMAbstractView</code>
					</li>
					<li>
						<code>view</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					الدولاب
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onWheel</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>DeltaMode</code> <code>deltaX</code> <code>deltaY</code> <code>deltaZ</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					الوسائط
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>OnAbort</code>
					</li>
					<li>
						<code>onCanPlay</code>
					</li>
					<li>
						<code>onCanPlayThrough</code>
					</li>
					<li>
						<code>onDurationChange</code>
					</li>
					<li>
						<code>onEmptied</code>
					</li>
					<li>
						<code>onEncrypted</code>
					</li>
					<li>
						<code>onEnded</code>
					</li>
					<li>
						<code>onError</code>
					</li>
					<li>
						<code>onLoadedData</code>
					</li>
					<li>
						<code>onLoadedMetadata</code>
					</li>
					<li>
						<code>onLoadStart</code>
					</li>
					<li>
						<code>onPauseonPlay</code>
					</li>
					<li>
						<code>onPlaying</code>
					</li>
					<li>
						<code>onProgress</code>
					</li>
					<li>
						<code>onRateChange</code>
					</li>
					<li>
						<code>onSeeked</code>
					</li>
					<li>
						<code>onSeeking</code>
					</li>
					<li>
						<code>onStalled</code>
					</li>
					<li>
						<code>onSuspend</code>
					</li>
					<li>
						<code>onTimeUpdate</code>
					</li>
					<li>
						<code>onVolumeChange</code>
					</li>
					<li>
						<code>onWaiting</code>
					</li>
				</ul>
</td>
			<td>
				<p>
					 
				</p>
			</td>
		</tr>
<tr>
<td>
				<p>
					الصور
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onLoad</code> <code>onError</code>
					</li>
				</ul>
</td>
			<td>
				<p>
					 
				</p>
			</td>
		</tr>
<tr>
<td>
				<p>
					الحركات
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onAnimationStart</code>
					</li>
					<li>
						<code>onAnimationEnd</code>
					</li>
					<li>
						<code>onAnimationIteration</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>animationName</code>
					</li>
					<li>
						<code>pseudoElement</code>
					</li>
					<li>
						<code>elapsedTime</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				<p>
					الانتقالات
				</p>
			</td>
			<td>
				<ul>
<li>
						<code>onTransitionEnd</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>propertyName</code>
					</li>
					<li>
						<code>pseudoElement</code>
					</li>
					<li>
						<code>elapsedTime</code>
					</li>
				</ul>
</td>
		</tr>
</tbody>
</table>
<h3>
	ملاحظات
</h3>

<ul>
<li>
		توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات.
	</li>
	<li>
		تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة <code>"Capture"</code> إلى اسم الحدث، أي أنَّ الحدث <code>onClick</code> سيصبح <code>onClickCapture</code>).
	</li>
	<li>
		إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية <code>nativeEvent</code> في كائن <code>SyntheticEvent</code> المُمرَّر إلى دالة معالجة الأحداث في React.
	</li>
	<li>
		لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation).
	</li>
	<li>
		يجب استخدام <code>e.stopPropagation()‎</code> أو <code>e.preventDefault()‎</code> يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام <code>return false;</code>‎.
	</li>
	<li>
		لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام <a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">توابع </a><a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">دورة الحياة</a> في React.
	</li>
</ul>
<h2>
	تركيب المكونات
</h2>

<p>
	إذا لم يكن واضحًا لك أنَّ مكوِّنات React تستطيع أن تستخدم مكوِّنات React الأخرى فاعلم أنَّها تستطيع فعل ذلك. فيمكن أن تحتوي دالة الضبط render عند تعريف أحد مكوِّنات React إشارةً إلى المكونات الأخرى. فعندما يحتوي مكوِّنٌ ما على مكوِّنٍ آخر فيمكننا أن نقول أنَّ المكوِّن الأب «يمتلك» مكوِّنًا ابنًا (وهذا يسمى بالتركيب [composition]).
</p>

<p>
	في الشيفرة أدناه، يحتوي (أو يمتلك) المكوِّن <code>BadgeList</code> المكوِّنين <code>BadgeBill</code> و <code>BadgeTom</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_30" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeBill</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Bill</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;;}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeTom</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Tom</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;;}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BadgeList</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

    </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">BadgeBill</span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="typ">BadgeTom</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">


  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">BadgeList</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	جعلتُ الشيفرة السابقة بسيطةً عمدًا لتوضيح كيفية تركيب المكونات، وسنلقي في <a href="https://academy.hsoub.com/programming/javascript/react/%D8%AE%D8%A7%D8%B5%D9%8A%D8%A7%D8%AA-%D9%85%D9%83%D9%88%D9%86%D8%A7%D8%AA-react-react-component-properties-r835/" rel="">الدرس القادم</a> نظرةً عن كيفية كتابة شيفرات التي تستخدم الخاصيات <code>props</code> لإنشاء مكوِّن <code>Badge</code> عام (generic). يمكن أن يأخذ المكوِّن العام <code>Badge</code> أي قيمة مقارنةً مع كتابة <code>Badge</code> مكتوبٌ فيه الاسم سابقًا.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		سمة أساسية لكتابة واجهات مستخدم قابلة للصيانة والإدارة هو تركيب المكوِّنات. صُمِّمَت مكوِّنات React لتحتوي على مكوِّناتٍ أخرى.
	</li>
	<li>
		لاحظ كيف تندمج شيفرة HTML والمكونات المُعرَّفة مسبقًا مع بعضهما بعضًا في دالة الضبط <code>render()</code>‎.
	</li>
</ul>
<h2>
	استيعاب دورة حياة المكوِّن
</h2>

<p>
	تمرّ مكوِّنات React بأحداث خلال حياتها وتسمى هذه الأحداث بدورة الحياة (lifecycle events). ترتبط هذه الأحدث بتوابع دورة الحياة. يمكنك أن تتذكر أننا ناقشنا بعض تلك التوابع في بداية هذا الدرس عندما ناقشنا عملية إنشاء المكوِّنات.
</p>

<p>
	توابع دورة الحياة توفِّر ارتباطات مع مراحل وطبيعة المكوِّن. ففي المثال الآتي الذي استعرته من أحد الأقسام السابقة، سنُسجِّل وقوع أحداث دورة الحياة <code>componentDidMount</code> و <code>componentWillUnmount</code> و <code>getInitialState</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_32" style="">
<span class="kwd">var</span><span class="pln"> createReactClass </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'create-react-class'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// وتمرير كائن من خيارات الضبط Timer إنشاء المكون </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">  

     </span><span class="com">// this.state دالة تعيد كائنًا والذي سيصبح قيمة</span><span class="pln">
</span><span class="pln">    getInitialState</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">  

</span><span class="pln">        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">            secondsElapsed</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">startTime</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

</span><span class="pln">        </span><span class="pun">};</span><span class="pln">

</span><span class="pln">    </span><span class="pun">},</span><span class="pln">

</span><span class="pln">    tick</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تابع مخصص</span><span class="pln">

</span><span class="pln">        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">

</span><span class="pln">            secondsElapsed</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">secondsElapsed </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="pln">        </span><span class="pun">});</span><span class="pln">

</span><span class="pln">    </span><span class="pun">},</span><span class="pln">

</span><span class="pln">    componentDidMount</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// دالة رد النداء لدورة حياة المكوِّن</span><span class="pln">

</span><span class="pln">        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">interval </span><span class="pun">=</span><span class="pln"> setInterval</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">tick</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="pun">},</span><span class="pln">

</span><span class="pln">    componentWillUnmount</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// دالة رد النداء لدورة حياة المكوِّن</span><span class="pln">

</span><span class="pln">        clearInterval</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">interval</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="pun">},</span><span class="pln">

</span><span class="pln">    render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    
         </span><span class="com">// JSX باستخدام صيغة React دالة تعيد عقد</span><span class="pln">
</span><span class="pln">        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

            </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">                </span><span class="typ">Seconds</span><span class="pln"> </span><span class="typ">Elapsed</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">secondsElapsed</span><span class="pun">}</span><span class="pln">

</span><span class="pln">            </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">


</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> startTime</span><span class="pun">=</span><span class="str">"60"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span><span class="pln"> </span><span class="com">// startTime تمرير قيمة الخاصية </span></pre>

<p>
	يمكن تقسيم هذه التوابع إلى ثلاثة تصنيفات: مرحلة التركيب (mount) والتحديث (update) والإزالة (unmount).
</p>

<p>
	سأعرض جدولًا في كل تصنيف يحتوي على توابع دورة الحياة الخاصة به.
</p>

<h3>
	مرحلة التركيب
</h3>

<p>
	تحدث مرحلة التركيب (mounting phase) مرةً واحدةً في دورة حياة المكوِّن، وهي أول مرحلة وتبدأ عندما نُهيِّئ المكوِّن، وفي هذه المرحلة ستُعرَّف وتُضبَط خاصيات وحالة المكوِّن، وسيُركَّب المكوِّن مع جميع أبنائه إلى واجهة المستخدم المُحدَّدة (سواءً كانت DOM أو UIView أو غيرها). وفي النهاية يمكننا أن نجري بعض عمليات المعالجة إن كان ذلك لازمًا.
</p>

<table>
<thead><tr>
<th>
				التابع
			</th>
			<th>
				الشرح
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				getInitialState()‎
			</td>
			<td>
				سيستدعى قبل تركيب المكوِّن، ويجب أن تعرِّف المكونات ذات الحالة (stateful) هذا التابع وتعيد بيانات الحالة الابتدائية.
			</td>
		</tr>
<tr>
<td>
				componentWillMount()‎
			</td>
			<td>
				سيستدعى مباشرةً قبل تركيب المكوِّن.
			</td>
		</tr>
<tr>
<td>
				componentDidMount()‎
			</td>
			<td>
				سيستدعى مباشرةً بعد تركيب المكوِّن. عملية التهيئة التي تتطلب وجود عقد DOM ستُعرَّف في هذا التابع.
			</td>
		</tr>
</tbody>
</table>
<h3>
	مرحلة التحديث
</h3>

<p>
	تقع مرحلة التحديث (updating phase) مرارًا وتكرارًا خلال دورة حياة المكوِّن، وفي هذه المرحلة يمكننا إضافة خاصيات جديدة أو تغيير الحالة أو معالجة تفاعلات المستخدم أو التواصل مع شجرة المكوِّنات، وسنقضي جُلَّ وقتنا في هذه المرحلة.
</p>

<table>
<thead><tr>
<th>
				التابع
			</th>
			<th>
				الشرح
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				componentWillReceiveProps(object nextProps)‎
			</td>
			<td>
				*
			</td>
		</tr>
<tr>
<td>
				shouldComponentUpdate(object nextProps, object nextState)‎
			</td>
			<td>
				سيستدعى عندما يقرر المكوِّن أنَّ أي تغييرات ستحتاج إلى تحديث شجرة DOM. إذا أردت استخدامه فيجب أن تقارن this.props مع nextProps و this.state مع nextState وتُعيد القيمة false لتخبر React بإمكانية تجاوز التحديث.
			</td>
		</tr>
<tr>
<td>
				componentWillUpdate(object nextProps, object nextState)‎
			</td>
			<td>
				سيستدعى مباشرةً قبل وقوع التحديث. لا يمكنك استدعاء this.setState()‎ هنا.
			</td>
		</tr>
<tr>
<td>
				componentDidUpdate(object prevProps, object prevState)‎
			</td>
			<td>
				سيستدعى مباشرةً بعد وقوع التحديث.
			</td>
		</tr>
</tbody>
</table>
<h3>
	مرحلة الإزالة
</h3>

<p>
	تقع مرحلة الإزالة (unmounting phase) مرةً واحدةً في دورة حياة المكوِّنات، وهي تحدث عند إزالة نسخة المكوِّن من واجهة المستخدم. ويمكن أن يحدث ذلك عندما ينتقل المستخدم إلى صفحة أخرى أو تتغير واجهة المستخدم أو اختفى المكوِّن …إلخ.
</p>

<table>
<thead><tr>
<th>
				التابع
			</th>
			<th>
				الشرح
			</th>
		</tr></thead>
<tbody><tr>
<td>
				componentWillUnmount()‎
			</td>
			<td>
				سيستدعى مباشرةً قبل إزالة المكوِّن وحذفه. يجب أن تأتي عمليات «التنظيف» هنا.
			</td>
		</tr></tbody>
</table>
<h3>
	ملاحظات
</h3>

<ul>
<li>
		التابعان componentDidMount و componentDidUpdate هما مكانان جيدان تضع فيهما البنى المنطقية للمكتبات.
	</li>
	<li>
		راجع توثيق React في موسوعة حسوب لتأخذ نظرةً تفصيليةً حول أحداث دورة حياة مكونات React.
	</li>
	<li>
		ترتيب مرحلة التركيب:
	</li>
	<li>
		التهيئة الابتدائية
		<ol>
<li>
				getDefaultProps()‎ ‏(React.createClass) أو MyComponent.defaultProps (صنف ES6)
			</li>
			<li>
				getInitialState()‎ ‏(React.createClass) أو this.state (دالة بانية في ES6)
			</li>
			<li>
				componentWillMount()‎
			</li>
			<li>
				render()‎
			</li>
		</ol>
</li>
	<li>
		عملية تهيئة الأبناء وضبط دورة حياتهم
		<ol>
<li>
				componentDidMount()‎
			</li>
		</ol>
</li>
	<li>
		ترتيب مرحلة التحديث:
		<ol>
<li>
				componentWillReceiveProps()‎
			</li>
			<li>
				shouldComponentUpdate()‎
			</li>
			<li>
				render()‎
			</li>
		</ol>
</li>
	<li>
		توابع دورة الحياة للأبناء
		<ol>
<li>
				componentWillUpdate()‎
			</li>
		</ol>
</li>
	<li>
		ترتيب مرحلة الإزالة:
		<ol>
<li>
				componentWillUnmount()‎
			</li>
			<li>
				توابع دورة الحياة للأبناء
			</li>
			<li>
				إزالة نسخة المكوِّن
			</li>
		</ol>
</li>
</ul>
<h2>
	الوصول إلى المكونات أو العقد الأبناء
</h2>

<p>
	إذا احتوى مكوِّنٌ على مكونات أبناء أو عقد React داخله (كما في <parent><child></child></parent> أو <parent><span>test</span></parent>) فيمكن الوصول إلى عقد React أو نسخ المكوِّنات الأبناء باستخدام الخاصية this.props.children.
</p>

<p>
	عند استخدام المكوِّن Parent في الشيفرة التالية، الذي يحتوي على عنصرَي
</p>

<div>
	والتي بدورها تحتوي على عقد React نصية. يمكن الوصول إلى جميع نسخ الأبناء داخل المكوِّن باستخدام this.props.children. وسأحاول في المثال الآتي أن أصل إليها داخل تابع دورة الحياة componentDidMount للعنصر الأب Parent:
	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_34" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Parent2</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  componentDidMount</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="com">// &lt;span&gt;child2text&lt;/span&gt; الوصول إلى  </span><span class="pln">
     </span><span class="com">// ولا حاجة لاستخدام مصفوفة لطالما كان هنالك ابن واحد فقط</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="com">// &lt;span&gt; لأننا نحصل على ابن العنصر child2text سينتج   </span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">);</span><span class="pln">


  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div </span><span class="pun">/&gt;;}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Parent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  componentDidMount</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="com">// &lt;div&gt;test&lt;/div&gt;&lt;div&gt;test&lt;/div&gt; الوصول إلى مصفوفة تحتوي على </span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="com">// في المصفوفة &lt;div&gt; لأننا نصل إلى أول عنصر childtext سينتج</span><span class="pln">

</span><span class="pln">    console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">[</span><span class="lit">1</span><span class="pun">].</span><span class="pln">props</span><span class="pun">.</span><span class="pln">children</span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">Parent2</span><span class="pun">&gt;&lt;</span><span class="pln">span</span><span class="pun">&gt;</span><span class="pln">child2text</span><span class="pun">&lt;</span><span class="str">/span&gt;&lt;/</span><span class="typ">Parent2</span><span class="pun">&gt;;}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">




  </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">

  </span><span class="pun">&lt;</span><span class="typ">Parent</span><span class="pun">&gt;&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">child</span><span class="pun">&lt;</span><span class="str">/div&gt;&lt;div&gt;childtext&lt;/</span><span class="pln">div</span><span class="pun">&gt;&lt;/</span><span class="typ">Parent</span><span class="pun">&gt;,</span><span class="pln">

  document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">)</span><span class="pln">

  </span><span class="pun">);</span></pre>

	<p>
		تعيد الخاصية this.props.children للمكوِّن Parent مصفوفةً تحتوي على إشارات لنسخ كائنات عقد React الأبناء. سنعرض هذه المصفوفة باستخدام console.log، أضف إلى ذلك أننا سنعرض في المكوِّن Parent قيمة العنصر الابن للعقدة الأولى (أي سنعرض قيمة العقدة النصية).
	</p>

	<div>
		<p>
			لاحظ عندما استخدمنا المكوِّن Parent2 داخل المكوِّن Parent كان المكوِّن Parent2 يحتوي على عقدة React وحيدة هي <span>child2text</span> وبالتالي ستكون قيمة الخاصية this.props.children في تابع دورة الحياة componentDidMount للمكوِّن Parent2 هي إشارة مباشرة إلى عقدة <span> في React، وليست مصفوفةً تحتوي على عنصرٍ وحيد.</span>
		</p>

		<p>
			ولمّا كان من المحتمل أن تعيد الخاصية this.props.children مجموعةً واسعةً من العقد، فتوفِّر React مجموعةً من الأدوات للتعامل معها، وهذه الأدوات مذكورة في الجدول أدناه.
		</p>

		<table>
<thead><tr>
<th>
						الأداة
					</th>
					<th>
						الشرح
					</th>
				</tr></thead>
<tbody>
<tr>
<td>
						<a href="https://wiki.hsoub.com/React/react_api#React.Children.map" rel="external">React.Children.map(this.props.children, function(){})</a>‎
					</td>
					<td>
						تستدعي دالة لكل عنصر ابن مباشر موجود ضمن children مع تعيين this إلى قيمة thisArg. إن كان children عبارة عن جزء (fragment) مع مفتاح أو مصفوفة فلن تُمرَّر الدالة للكائن الحاوي. إن كانت قيمة children هي null أو undefined فستُعيد null أو undefined بدلًا من المصفوفة.
					</td>
				</tr>
<tr>
<td>
						<a href="https://wiki.hsoub.com/React/react_api#React.Children.forEach" rel="external">React.Children.forEach(this.props.children, function(){})</a>‎
					</td>
					<td>
						مماثلة للتابع React.Children.map()‎ ولكن لا تُعيد مصفوفة.
					</td>
				</tr>
<tr>
<td>
						<a href="https://wiki.hsoub.com/React/react_api#React.Children.count" rel="external">React.Children.count(this.props.children)</a>‎
					</td>
					<td>
						تُعيد العدد الكلي للمكوّنات الموجود ضمن children، مُكافئ لعدد المرات التي يُمرَّر فيها رد النداء إلى map أو التي يُستدعى فيها forEach.
					</td>
				</tr>
<tr>
<td>
						<a href="https://wiki.hsoub.com/React/react_api#React.Children.only" rel="external">React.Children.only(this.props.children)</a>‎
					</td>
					<td>
						تتحقّق من أنّ children يمتلك فقط ابنًا واحدًا (عنصر React) وتُعيده. فيما عدا ذلك سيرمي هذا التابع خطأً.
					</td>
				</tr>
<tr>
<td>
						<a href="https://wiki.hsoub.com/React/react_api#React.Children.toArray" rel="external">React.Children.toArray(this.props.children)</a>‎
					</td>
					<td>
						تُعيد بنية البيانات children كمصفوفة مع تعيين مفتاح لكل عنصر ابن. تكون مفيدةً إن أردت التعامل مع مجموعة من العناصر الأبناء في توابع التصيير لديك، خاصّة إن أردت إعادة ترتيب أو تجزئة this.props.children قبل تمريره.
					</td>
				</tr>
</tbody>
</table>
<h3>
			ملاحظات
		</h3>

		<ul>
<li>
				عندما يكون هنالك عنصرٌ ابن وحيد، فستكون قيمة this.props.children هي العنصر نفسه دون أن يحتوى في مصفوفة. وهذا يوفِّر عملية تهيئة المصفوفة.
			</li>
			<li>
				قد يربكك بدايةً أنَّ قيمة children ليست ما يعيده المكوِّن، وإنما ما هو محتوى داخل المكوِّن.
			</li>
		</ul>
<h2>
			استخدام الخاصيات ref
		</h2>

		<p>
			تجعل الخاصية <a href="https://wiki.hsoub.com/React/refs_and_the_dom" rel="external">ref</a> من الممكن تخزين نسخة من عنصر أو مكوِّن React معيّن باستخدام دالة الضبط render()‎. وهذا مفيدٌ جدًا عندما تريد الإشارة من داخل المكوِّن إلى عنصر أو مكوِّن آخر محتوى داخل الدالة render()‎.
		</p>

		<p>
			لإنشاء مرجعية، ضع الخاصية ref مع ضبط دالة كقيمةٍ لها في أي عنصر أو مكوِّن، ثم من داخل الدالة سيكون أول معامل (parameter) داخل مجال الدالة يشير إلى العنصر أو المكوِّن الذي عُرِّفَت الخاصية ref عليه.
		</p>

		<p>
			على سبيل المثال، سنعرض المحتويات المرجعية المشار إليها باستخدام ref عبر console.log:
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_36" style="">
<span class="kwd">class</span><span class="pln"> C2 extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">span ref</span><span class="pun">={</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">span</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">span</span><span class="pun">)}}</span><span class="pln"> </span><span class="pun">/&gt;}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> C1 extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pun">(</span><span class="pln">

    </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;</span><span class="pln">C2 ref</span><span class="pun">={</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">c2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">c2</span><span class="pun">)}}&gt;&lt;/</span><span class="pln">C2</span><span class="pun">&gt;</span><span class="pln">

      </span><span class="pun">&lt;</span><span class="pln">div ref</span><span class="pun">={</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">div</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">div</span><span class="pun">)}}&gt;&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

  </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="pln">C1 ref</span><span class="pun">={</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">ci</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">ci</span><span class="pun">)}}</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln">document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

		<p>
			لاحظ أنَّ الإشارات إلى المرجعيات تعيد نسخ المكوِّنات، بينما الإشارات إلى عناصر React تعيد مرجعيات إلى عناصر DOM في شجرة DOM الحقيقية (أي ليست مرجعيةً تشير إلى شجرة DOM الافتراضية، وإنما شجرة DOM الحقيقية).
		</p>

		<p>
			استخدامٌ شائعٌ للخاصية ref هو تخزين مرجعية إلى نسخة المكوِّن. ففي الشيفرة الآتية سأستخدم دالة رد نداء ref على حقل إدخال input نصي لتخزين مرجعية لنسخة المكوِّن لكي تستطيع التوابع الأخرى الوصول إليها عبر الكلمة المحجوزة this (كما في this.textInput.focus()‎):
		</p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_38" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  constructor</span><span class="pun">(</span><span class="pln">props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    super</span><span class="pun">(</span><span class="pln">props</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">handleClick </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">handleClick</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  handleClick</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="com">// DOM <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> التركيز على المحتوى النصية باستخدام </span><span class="pln">

</span><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">textInput</span><span class="pun">.</span><span class="pln">focus</span><span class="pun">();</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="com">// قيمة الخاصية ref هي دالة رد نداء التي تؤدي إلى</span><span class="pln">

</span><span class="pln">    </span><span class="com">// عند تركيب المكون this.textInput الإشارة إلى  </span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

      </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">&lt;</span><span class="pln">input type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln"> ref</span><span class="pun">={(</span><span class="pln">thisInput</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">textInput </span><span class="pun">=</span><span class="pln"> thisInput</span><span class="pun">}}</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">&lt;</span><span class="pln">input

</span><span class="pln">          type</span><span class="pun">=</span><span class="str">"button"</span><span class="pln">

</span><span class="pln">          value</span><span class="pun">=</span><span class="str">"Focus the text input"</span><span class="pln">

</span><span class="pln">          onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">handleClick</span><span class="pun">}</span><span class="pln">

</span><span class="pln">        </span><span class="pun">/&gt;</span><span class="pln">

</span><span class="pln">      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">    </span><span class="pun">);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">

  </span><span class="pun">&lt;</span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln">

  document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">)</span><span class="pln">

</span><span class="pun">);</span></pre>

		<h3>
			ملاحظات
		</h3>

		<ul>
<li>
				لا يمكن ربط ref مع دالة عديم الحالة لأنَّ المكوِّن لا يملك نسخةً (instance) بعد.
			</li>
			<li>
				ربما تشاهد الخاصية ref مع سلسلة نصية بدلًا من دالة؛ وهذا أمرٌ مهمل في الإصدارات المستقبلية، ومن المُفضَّل استخدام الدوال.
			</li>
			<li>
				ستستدعى دالة رد نداء ref مباشرةً بعد تركيب المكوِّن.
			</li>
			<li>
				تسمح لنا الإشارات إلى نسخة المكوِّن باستدعاء توابع مخصصة على المكوِّن إذا كانت موجودةً عند تعريفه.
			</li>
			<li>
				كتابة المراجع مع تعبير تعريف دالة سطري يعني أنَّ React سترى كائن دالة مختلف في كل تحديث، وستستدعى ref مع القيمة null مباشرةً قبل استدعائها مع نسخة المكوِّن، أي أنَّ نسخة المكون ستزال في كل تغيير لقيمة ref وستستدعى ref القديمة مع القيمة null كوسيط.
			</li>
			<li>
				يبين توثيق React ملاحظةً مهمةً «ربّما تكون رغبتك الأولى لاستخدام المراجع هي تحقيق كل ما تُريده في تطبيقك. إن كانت هذه حالتك فخُذ لحظة للتفكير حول المكان المُلائم لوضع الحالة في التسلسل الهرمي للمُكوِّنات. يتضح عادةً أنّ المكان المناسب لوضع الحالة هو في المستويات العليا من التسلسل الهرمي للمُكوِّنات.».
			</li>
		</ul>
<h2>
			إجبار إعادة تصيير العنصر
		</h2>

		<p>
			من المرجّح أنَّ: لاحظتَ أنَّ استدعاء ReactDOM.render()‎ هو عملية التحميل الابتدائية للمكوِّن وجميع المكونات الفرعية له. وبعد عملية التركيب الابتدائية للمكوِّنات، ستحدث إعادة التصيير عندما:
		</p>

		<ol>
<li>
				استدعي التابع setState()‎ في المكوِّن
			</li>
			<li>
				استدعي التابع forceUpdate()‎ في المكوِّن
			</li>
		</ol>
<p>
			في أي وقت يجير إعادة تصيير المكوِّن (أو يُصيّر التصيير الابتدائي) فستُصيّر جميع المكوِّنات الأبناء التابعة له داخل شجرة DOM الافتراضية والتي قد تُسبِّب تغييرًا في شجرة DOM الحقيقية (أي واجهة المستخدم). ما أريد إيصاله لك هنا هو أنَّ إعادة تصيير أحد المكوِّنات في شجرة DOM الافتراضية لا يعني بالضرورة أنَّ تحديثًا سيطرأ على شجرة DOM الحقيقية.
		</p>

		<p>
			في المثال أدناه، سيبدأ استدعاء ReactDOM.render(&lt; App / &gt;, app);‎ عملية التصيير، والذي سيؤدي إلى تصيير <app> و <timer>، عملية إعادة التصيير التالية ستحدث عند استخدام setInterval()‎ لتابع المكوِّن setState()‎ الذي سيؤدي إلى إعادة تصيير <app> و <timer>، لاحظ كيف ستتغير واجهة المستخدم عند تغيير حالة now:</timer></app></timer></app></p>

		<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2323_40" style="">
<span class="kwd">var</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">

</span><span class="pln">    render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

          </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">now</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">)</span><span class="pln">

</span><span class="pln">    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">




</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">App</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln">

  getInitialState</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">now</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">.</span><span class="pln">now</span><span class="pun">()};</span><span class="pln">

  </span><span class="pun">},</span><span class="pln">




  componentDidMount</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">    </span><span class="kwd">var</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> setInterval</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">now</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">.</span><span class="pln">now</span><span class="pun">()});</span><span class="pln">

</span><span class="pln">    </span><span class="pun">}.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">),</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">);</span><span class="pln">




</span><span class="pln">    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span><span class="pln"> clearInterval</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">);</span><span class="pln"> </span><span class="pun">},</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">);</span><span class="pln">

</span><span class="pln">    </span><span class="com">// .forceUpdate() لا تفعل هذا! هذا مجرد مثال توضيحي عن استخدام  </span><span class="pln">

</span><span class="pln">    setTimeout</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">now </span><span class="pun">=</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">forceUpdate</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">),</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">);</span><span class="pln">

  </span><span class="pun">},</span><span class="pln">



  render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="pln">      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">

          </span><span class="pun">&lt;</span><span class="typ">Timer</span><span class="pln"> now</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">now</span><span class="pun">}&gt;&lt;/</span><span class="typ">Timer</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pln">        </span><span class="pun">)</span><span class="pln">

</span><span class="pln">    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">});</span><span class="pln">




</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="pln"> </span><span class="typ">App</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

		<p>
			تحدث عملية إعادة التصيير الآتية عند تشغيل setTimout()‎ واستدعاء التابع this.forceUpdate()‎ لاحظ أنَّ تحديث الحالة (this.state.now = 'foo';‎) لن تؤدي بمفردها إلى إعادة التصيير. ضبنا بداية الحالة باستخدام this.state ثم استدعينا this.forceUpdate()‎ لكي يعاد تصيير العنصر مع الحالة الجديدة.
		</p>

		<h3>
			ملاحظات
		</h3>

		<p>
			لا تُحدِّث الحالة باستخدام this.state إطلاقًا! فعلنا ذلك في المثال السابق لتبيين طريقة استخدام this.forceUpdate()‎ فحسب.
		</p>

		<p>
			ترجمة -وبتصرف- للفصل <a href="https://www.reactenlightenment.com/basic-react-components.html" rel="external nofollow">Basic React Components</a> من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
		</p>
	</div>
</div>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
]]></description><guid isPermaLink="false">834</guid><pubDate>Wed, 19 Feb 2020 18:00:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x635;&#x64A;&#x63A;&#x629; JavaScript Syntax Extension) JSX)</title><link>https://academy.hsoub.com/programming/javascript/react/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%B5%D9%8A%D8%BA%D8%A9-javascript-syntax-extension-jsx-r777/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e16416290572___React_5.jpg.491686bb04457631ae8cf9b60c914f12.jpg" /></p>

<p>
	تعلمنا في <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-r776/" rel="">المقال السابق</a> كيفية إنشاء عقد React باستخدام شيفرات JavaScript العادية، وسنلقي في هذا المقال نظرةً على إنشاء عقد React باستخدام <a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">صيغة</a> <a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">JSX</a>. إن لم تقرأ المقال السابق، <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-r776/" rel="">عقد React</a>، فانتقل إليه أولًا لقراءته ثم عد إلى هذا المقال.
</p>

<p>
	سنستخدم صيغة JSX بعد هذا المقال في بقية الكتاب ما لم نستعمل الدالة <code>React.createElement()‎</code> لأغراض التوضيح.
</p>

<p>
	بعد انتهائك من قراءة هذا المقال، يمكنك الاطلاع على <a href="https://wiki.hsoub.com/React/jsx_in_depth" rel="external">شرح تفصيلي لجميع ميزات</a> <a href="https://wiki.hsoub.com/React/jsx_in_depth" rel="external">JSX</a> في موسوعة حسوب.
</p>

<h2>
	ما هي صيغة JSX؟
</h2>

<p>
	JSX هي صيغة شبيهة بصيغة XML أو HTML التي تستخدمها React لتوسعة ECMAScript لكي نستطيع كتابة تعابير شبيهة بلغة XML أو HTML داخل شيفرة JavaScript. هذه الصيغة مهيئة للعمل مع برمجيات التحويل مثل Babel لتحويل النص الشبيه بشيفرات HTML في ملفات JavaScript إلى كائنات JavaScript التي تستطيع محركات JavaScript تفسيرها.
</p>

<p>
	أساسيًا، عند استخدمنا لصيغة JSX يمكننا أن نكتب بنى شبيهة ببنى HTML (أي هياكل من العناصر كما في DOM) بنفس الملف الذي تكتب فيه شيفرة JavaScript، ثم يحوِّل Babel هذه التعابير إلى شيفرة JavaScript حقيقية. وعلى عكس ما جرت عليه العادة بوضع شيفرات JavaScript داخل HTML، تسمح لنا صيغة JSX بوضع شيفرات HTML داخل JavaScript.
</p>

<p>
	تسمح لنا JSX بكتابة شيفرة JavaScript الآتية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_7" style="">
<span class="kwd">var</span><span class="pln"> nav </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">ul id</span><span class="pun">=</span><span class="str">"nav"</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">li</span><span class="pun">&gt;&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"#"</span><span class="pun">&gt;</span><span class="typ">Home</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">li</span><span class="pun">&gt;&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"#"</span><span class="pun">&gt;</span><span class="typ">About</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">li</span><span class="pun">&gt;&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"#"</span><span class="pun">&gt;</span><span class="typ">Clients</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">li</span><span class="pun">&gt;&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"#"</span><span class="pun">&gt;</span><span class="typ">Contact</span><span class="pln"> </span><span class="typ">Us</span><span class="pun">&lt;</span><span class="str">/a&gt;&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;/</span><span class="pln">ul</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	وسيحولها Babel إلى الشيفرة الآتية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_9" style="">
<span class="kwd">var</span><span class="pln"> nav </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
   </span><span class="str">"ul"</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nav"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
   </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
      </span><span class="str">"li"</span><span class="pun">,</span><span class="pln">
      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
         </span><span class="str">"a"</span><span class="pun">,</span><span class="pln">
         </span><span class="pun">{</span><span class="pln"> href</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
         </span><span class="str">"Home"</span><span class="pln">
      </span><span class="pun">)</span><span class="pln">
   </span><span class="pun">),</span><span class="pln">
   </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
      </span><span class="str">"li"</span><span class="pun">,</span><span class="pln">
      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
         </span><span class="str">"a"</span><span class="pun">,</span><span class="pln">
         </span><span class="pun">{</span><span class="pln"> href</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
         </span><span class="str">"About"</span><span class="pln">
      </span><span class="pun">)</span><span class="pln">
   </span><span class="pun">),</span><span class="pln">
   </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
      </span><span class="str">"li"</span><span class="pun">,</span><span class="pln">
      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
         </span><span class="str">"a"</span><span class="pun">,</span><span class="pln">
         </span><span class="pun">{</span><span class="pln"> href</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
         </span><span class="str">"Clients"</span><span class="pln">
      </span><span class="pun">)</span><span class="pln">
   </span><span class="pun">),</span><span class="pln">
   </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
      </span><span class="str">"li"</span><span class="pun">,</span><span class="pln">
      </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
      </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
         </span><span class="str">"a"</span><span class="pun">,</span><span class="pln">
         </span><span class="pun">{</span><span class="pln"> href</span><span class="pun">:</span><span class="pln"> </span><span class="str">"#"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
         </span><span class="str">"Contact Us"</span><span class="pln">
      </span><span class="pun">)</span><span class="pln">
   </span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	لذا يمكننا أن نعدّ JSX على أنها اختصار لاستدعاء <code>React.createElement()</code>‎.
</p>

<p>
	فكرة دمج شيفرات HTML و JavaScript في نفس الملف هي فكرة مثيرة للجدال، حاول أن تتجاهل ذلك وتستعملها إذا وجدتها مفيدةً، وإذا لم تجدها مفيدةً فاكتب شيفرة JavaScript الضرورية لإنشاء عقد React يدويًا، فالخيار عائد لك تمامًا. أرى شخصيًا أنَّ JSX توفِّر صيغة مختصرة ومألوفةً لتعريف بنى هيكلية مع الخاصيات اللازمة لها والتي لا تتطلب تعلّم صيغة قوالب خاصة أو تتطلب الخروج من شيفرة JavaScript؛ وكلا الميزتين السابقتين مفيدتان عند إنشاء التطبيقات الكبيرة.
</p>

<p>
	من الواضح أنَّ صيغة JSX أسهل قراءةً وكتابةً من الأهرامات الكبيرة من استدعاءات دوال JavaScript مع تعريف الكائنات داخلها (قارن الشيفرتين السابقتين في هذا القسم لتتأكد من ذلك). أضف إلى ذلك أنَّ فريق تطوير React يعتقد أنَّ JSX أفضل لتعريف واجهات المستخدم من أحد حلول القوالب (مثل Handlebars):
</p>

<p>
	«إنَّ الشيفرة البرمجية والبنى الهيكلية مرتبطتان مع بعضهما بعضًا ارتباطًا وثيقًا. أضف إلى ذلك أنَّ الشيفرات البرمجية معقدة جدًا واستخدام لغات القوالب ستجعل الأمر صعبًا جدًا. وجدنا أنَّ أفضل حل لهذه المشكلة هو توليد شيفرات HTML مباشرةً من شيفرة JavaScript، وبهذا نستطيع استخدام كامل قدرات لغة برمجية حقيقية لبناء واجهات المستخدم.»
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			لا تفكر في JSX على أنها لغة قوالب، وإنما هي صيغة JavaScript خاصة يمكن تصريفها، أي أنَّ JSX هي صيغة تسمح بتحويل بنى شبيهة ببنى HTML إلى شيفرات JavaScript.
		</p>
	</li>
	<li>
		<p>
			أداة Babel هي الأداة التي اختارها فريق تطوير React لتحويل شيفرات ES*‎ و JSX إلى شيفرة ES5. يمكنك معرفة المزيد عن Babel بقراءة <a href="https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md" rel="external nofollow">توثيقه الرسمي</a>.
		</p>
	</li>
	<li>
		<p>
			باستخدام صيغة JSX:
		</p>

		<ul>
<li>
				<p>
					أصبح بإمكان الأشخاص غير المتخصصين تقنيًا فهم وتعديل الأجزاء المطلوبة. فيجد مطورو CSS والمصممون صيغة JSX أكثر ألفةً من شيفرة JavaScript.
				</p>
			</li>
			<li>
				<p>
					يمكنك استثمار كامل قدرات JavaScript في HTML وتتجنب تعلّم أو استخدام لغة خاصة بالقوالب. لكن اعلم أن JSX ليس محرّك قوالب، وإنما صيغة تصريحية للتعبير عن البنية الهيكلية الشجرية لمكونات UI.
				</p>
			</li>
			<li>
				<p>
					سيجد المُصرِّف (compiler) أخطاءً في شيفرة HTML الخاصة بك كنتَ ستغفل عنها.
				</p>
			</li>
			<li>
				<p>
					تحث صياغة JSX على فكر استخدام الأنماط السطرية (inline styles) وهو أمرٌ حسن.
				</p>
			</li>
		</ul>
</li>
	<li>
		<p>
			صيغة JSX منفصلة عن React، ولا تحاول JSX أن تتفق مع أي مواصفة تخص HTML أو XML، وإنما هي مصممة كميزة ECMAScript وهي تشبه HTML ظاهريًا فقط، <a href="https://facebook.github.io/jsx/" rel="external nofollow">و</a><a href="https://facebook.github.io/jsx/" rel="external nofollow">تجري كتابة مواصفة</a> <a href="https://facebook.github.io/jsx/" rel="external nofollow">JSX</a> كمسودة لكي تُستخدَم من أي شخص كإضافة لصياغة ECMAScript.
		</p>
	</li>
	<li>
		<p>
			في صيغة JSX، يجوز استخدام ‎<code>&lt;foo-bar /&gt;</code>‎ بمفرده، لكن لا يجوز استخدام <code>&lt;foo-bar&gt;</code>. أي عليك إغلاق جميع الوسوم دومًا.
		</p>
	</li>
</ul>
<h2>
	إنشاء عقد React باستخدام JSX
</h2>

<p>
	بإكمالنا لما تعلمناه في <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-r776/" rel="">المقال الماضي</a>، يجب أن تكون قادرًا على إنشاء عقد React باستخدام الدالة <code>React.createElement()</code>‎. فيمكن مثلًا استخدام هذه الدالة لإنشاء عقد React التي تُمثِّل عقدًا حقيقيةً في HTML DOM إضافةً إلى عقدٍ مخصصة. سأريك حالتي الاستخدام السابقتين في المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7976_8" style="">
<span class="com">// حقيقية HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLLi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">className</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مخصصة HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLCustom</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'foo-bar'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">className</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">);</span></pre>

<p>
	لاستخدام صيغة JSX بدلًا من <code>React.createElement()‎</code> لإنشاء هذه العقد، فكل ما علينا فعله هو تبديل استدعاءات الدالة <code>React.createElement()</code>‎ إلى وسوم شبيهة بوسوم HTML التي تُمثِّل عناصر HTML التي تريد إنشاء شجرة DOM الافتراضية بها. يمكننا أن نكتب الشيفرة السابقة بصيغة JSX كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7976_10" style="">
<span class="com">// حقيقية HTML DOM التي تمثِّل عقدة React عقدة    </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLLi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">li className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="com">// مخصصة HTML DOM التي تمثِّل عقدة React عقدة    </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLCustom</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar</span><span class="pun">&gt;;</span></pre>

<p>
	لاحظ أنَّ صيغة JSX غير محتواة في سلسلة نصية في JavaScript، وتكتبها كأنك تكتب الشيفرة داخل ملف <code>‎.html</code>عادي، وكما ذكرنا لعدّة مرات، ستحوِّل صيغة JSX إلى استدعاءات للدالة <code>React.createElement()</code>‎ باستخدام Babel:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7976_12" style="">
<span class="com">// حقيقية HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLLi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">li className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="com">// مخصصة HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLCustom</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLCustom</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app2'</span><span class="pun">));</span></pre>

<p>
	إذا أردتَ تفحص شيفرة HTML الناتجة عن المثال السابق، فستجد أنَّها شبيهة بهذه الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_17" style="">
<span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app1"</span><span class="tag">&gt;&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/li&gt;&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app2"</span><span class="tag">&gt;&lt;foo-bar</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".1"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/foo-bar&gt;&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	إنشاء عقد React باستخدام JSX سهل جدًا كما لو كنتَ تكتب شيفرة HTML داخل ملفات JavaScript.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			تدعم JSX صيغة إغلاق الوسوم الخاصة بلغة XML، لذا يمكنك أن تهمل إضافة وسم الإغلاق إذا لم يمتلك العنصر أي أبناء.
		</p>
	</li>
	<li>
		<p>
			إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<code>&lt;``x-my-component custom-attribute="foo" /&gt;‎</code>).
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>class</code> يجب أن تكتب <code>className</code>.
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>for</code> يجب أن تكتب <code>htmlFor</code>.
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>style</code> تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي <code>background-color</code> تصبح <code>backgroundColor</code>).
		</p>
	</li>
	<li>
		<p>
			جميع الخاصيات مكتوبة بالصيغة المستخدمة في JavaScript، وذلك بحذف الشرطة وجعل الحرف الذي يليها كبيرًا (أي <code>accept-charset</code> ستصبح <code>acceptCharset</code>).
		</p>
	</li>
	<li>
		<p>
			لتمثيل عناصر HTML احرص على كتابة الوسوم بحرفٍ صغير.
		</p>
	</li>
	<li>
		<p>
			هذه هي قائمة بجميع خاصيات HTML التي تدعمها React:
		</p>
	</li>
</ul>
<pre class="ipsCode">
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap
</pre>

<h2>
	تصيير JSX إلى DOM
</h2>

<p>
	يمكن استخدام الدالة <code>ReactDOM.render()</code>‎ لتصيير تعابير JSX إلى DOM. في الواقع، كل ما تفعله Babel هو تحوي JSX إلى <code>React.createElement()</code>‎.
</p>

<p>
	في المثال الآتي، سنُصيّر العنصر <code>&lt;li&gt;</code> والعنصر المخصص <code>&lt;foo-bar&gt;</code> إلى DOM باستخدام تعابير JSX:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7976_14" style="">
<span class="com">// حقيقية HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLLi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">li className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="com">// مخصصة HTML DOM التي تمثِّل عقدة React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLCustom</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar className</span><span class="pun">=</span><span class="str">"bar"</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">foo</span><span class="pun">&lt;/</span><span class="pln">foo</span><span class="pun">-</span><span class="pln">bar</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="com">// &lt;div id="app1"&gt;&lt;/div&gt; إلى HTMLLi باسم React تصيير عقدة</span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span><span class="pln">

</span><span class="com">// &lt;div id="app2"&gt;&lt;/div&gt; إلى HTMLCustom باسم React تصيير عقدة</span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLCustom</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app2'</span><span class="pun">));</span></pre>

<p>
	ستبدو شيفرة HTML كما يلي بعد تصيير العناصر إلى DOM:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_21" style="">
<span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app1"</span><span class="tag">&gt;&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/li&gt;&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app2"</span><span class="tag">&gt;&lt;foo-bar</span><span class="pln"> </span><span class="atn">classname</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">children</span><span class="pun">=</span><span class="atv">"foo"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".1"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/foo-bar&gt;&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	تذكّر أنَّ Babel يأخذ JSX ويحولها إلى عقد React (أي استدعاءات الدالة <code>React.createElement()‎</code>) ثم باستخدام هذه العقد المُنشَأة باستخدام React (في شجرة DOM الافتراضية) سنُصيّر العناصر إلى شجرة DOM الحقيقية. ما تفعله الدالة <code>ReactDOM.render()‎</code> هو تحويل عقد React إلى عقد DOM حقيقة ثم إضافتها إلى مستند HTML.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			ستستبدل أي عقد DOM داخل عناصر DOM التي سيُصيَّر إليها (أي أنها ستُحذَف ويحلّ المحتوى الجديد محلها).
		</p>
	</li>
	<li>
		<p>
			الدالة <code>ReactDOM.render()‎</code> لا تعدِّل عقدة عنصر DOM الذي تُصيّر React إليه، وإنما تتطلَّب React ملكيةً كاملةً للعقدة النصية عند التصيير، فلا يجدر بك إضافة أبناء أو إزالة أبناء من العقدة التي تضيف React فيها المكوِّن أو العقدة.
		</p>
	</li>
	<li>
		<p>
			التصيير إلى شجرة HTML DOM هو أحد الخيارات فقط، فهنالك <a href="https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring" rel="external nofollow">خياراتٌ أخرى</a> ممكنة، فمثلًا تستطيع التصيير إلى سلسلة نصية (أي <code>ReactDOMServer.renderToString()</code>‎) في جهة الخادم.
		</p>
	</li>
	<li>
		<p>
			إعادة تصيير نفس عنصر DOM سيؤدي إلى تحديث العقد الأبناء الحاليين إذا حدث تغييرٌ فيها، أو إذا أُضيفت عقدة عنصر ابن جديدة.
		</p>
	</li>
	<li>
		<p>
			لا تستدعي <code>this.render()</code>‎ يدويًا أبدًا، اترك الأمر إلى React.
		</p>
	</li>
</ul>
<h2>
	استخدام تعابير JavaScript داخل JSX
</h2>

<p>
	آمل الآن أن يكون واضحًا أنَّ JSX هي صيغة بسيطة ستحوَّل في نهاية المطاف إلى شيفرة JavaScript حقيقة، لكن ماذا سيحدث عندما نريد تضمين شيفرة JavaScript حقيقية داخل JSX؟ كل ما علينا فعله لكتابة تعابير JavaScript داخل JSX هو وضعها ضمن قوسين معقوفين <code>{}</code>.
</p>

<p>
	في شيفرة React الآتية، سنضيف تعبيرًا من تعابير JavaScript (وهو 2+2) محاطًا بقوسين معقوفين <code>{}</code> التي ستُفسَّر من معالج JavaScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7976_16" style="">
<span class="kwd">var</span><span class="pln"> label </span><span class="pun">=</span><span class="pln"> </span><span class="str">'2 + 2'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> inputType </span><span class="pun">=</span><span class="pln"> </span><span class="str">'input'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// JSX لاحظ كيفية استخدام تعابير أو قيم جافاسكربت بين القوسين المعقوفين داخل صيغة </span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">label</span><span class="pun">&gt;{</span><span class="pln">label</span><span class="pun">}</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">input type</span><span class="pun">={</span><span class="pln">inputType</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">={</span><span class="lit">2</span><span class="pun">+</span><span class="lit">2</span><span class="pun">}</span><span class="pln"> </span><span class="pun">/&gt;&lt;/</span><span class="pln">label</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ستحوَّل شيفرة JSX إلى النتيجة الآتية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_25" style="">
<span class="kwd">var</span><span class="pln"> label </span><span class="pun">=</span><span class="pln"> </span><span class="str">'2 + 2'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> inputType </span><span class="pun">=</span><span class="pln"> </span><span class="str">'input'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
  </span><span class="str">'label'</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
  label</span><span class="pun">,</span><span class="pln">
  </span><span class="str">' = '</span><span class="pun">,</span><span class="pln">
  </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'input'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> type</span><span class="pun">:</span><span class="pln"> inputType</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">})</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	بعد أن تُفسَّر الشيفرة السابقة من محرِّك JavaScript (أي المتصفح)، فستُقدَّر قيمة تعابير JavaScript وستبدو شيفرة HTML كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_27" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;&lt;span</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.0"</span><span class="tag">&gt;</span><span class="pln">2 + 2</span><span class="tag">&lt;/span&gt;&lt;span</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.1"</span><span class="tag">&gt;</span><span class="pln"> = </span><span class="tag">&lt;/span&gt;&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"input"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"4"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.2"</span><span class="tag">&gt;&lt;/label&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	لا يوجد شيءٌ معقد في المثال السابق، بعد الأخذ بالحسبان أنَّ الأقواس ستُهرِّب شيفرة JSX. فالقوسان <code>{}</code> سيخبران JSX أنَّ المحتوى الموجود داخلهما هو شيفرة JavaScript فستتركها دون تعديل لكي يفسرها مُحرِّك JavaScript (أي التعبير <code>2+2</code>) لاحظ أنَّ القوسين <code>{}</code> يمكن أن يستخدما في أي مكان داخل تعابير JSX لطالما كانت نتيجتها هو تعبيرٌ صالحٌ في JavaScript.
</p>

<h2>
	استخدام تعليقات JavaScript داخل JSX
</h2>

<p>
	يمكنك وضع تعليقات JavaScript في أي مكان في شيفرة JSX عدا المواضع التي تتوقع فيها JSX عقدة React ابن. في هذه الحالة ستحتاج إلى تهريب (escape) التعليق باستخدام <code>{}</code> لكي تعلم JSX أنَّ عليها تمرير المحتوى كشيفرة JavaScript.
</p>

<p>
	تفحص الشيفرة الآتية، واحرص على فهم متى عليك إخبار JSX أن تُهرِّب تعليق JavaScript لكيلا تُنشَأ عقدة React ابن:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_29" style="">
<span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div </span><span class="com">/*comment*/</span><span class="pun">&gt;{</span><span class="com">/* use {} here to comment*/</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span></pre>

<p>
	إذا لم نضع التعليق في الشيفرة السابقة الموجود داخل العقدة
</p>

<div>
	ضمن القوسين <code>{}</code> فسيحاول Babel تحويل التعليق إلى عقدة React نصية، وسيكون الناتج -غير المتوقع- دون استخدام <code>{}</code> كما يلي:

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_31" style="">
<span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
  </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">
  </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"/* use "</span><span class="pun">,</span><span class="pln">
  </span><span class="str">" here to comment*/"</span><span class="pln"> 
</span><span class="pun">);</span></pre>

	<p>
		مما سينُتِج شيفرة HTML الآتية التي تحتوي على عقد نصية أُنشِئت خطأً:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_33" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.0"</span><span class="tag">&gt;</span><span class="pln">/* use </span><span class="tag">&lt;/span&gt;&lt;span</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.1"</span><span class="tag">&gt;</span><span class="pln"> here to comment*/</span><span class="tag">&lt;/span&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>
	<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}	</style>
<h2>
		استخدام أنماط CSS داخل JSX
	</h2>

	<p>
		لتعريف أنماط CSS ضمن صيغة JSX، فعلينا تمرير مرجعية إلى كائنٍ يحتوي على خاصيات CSS وقيمها إلى الخاصية style.
	</p>

	<p>
		سنُهيّئ في بداية المثال الآتي كائن JavaScript باسم styles يحتوي على الأنماط التي نريد تضمينها سطريًا في JSX، ثم سنستخدم القوسين <code>{}</code> للإشارة إلى الكائن الذي يجب أن يُستخدَم كقيمة للأنماط (مثل <code>style={styles}‎</code>):
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_35" style="">
<span class="kwd">var</span><span class="pln"> styles </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    color</span><span class="pun">:</span><span class="pln"> </span><span class="str">'red'</span><span class="pun">,</span><span class="pln">
    backgroundColor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'black'</span><span class="pun">,</span><span class="pln">
    fontWeight</span><span class="pun">:</span><span class="pln"> </span><span class="str">'bold'</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">styles</span><span class="pun">}&gt;</span><span class="pln">test</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span></pre>

	<p>
		لاحظ أنَّ خاصيات CSS المُضمَّنة سطريًا مكتوبة بطريقة كتابة خاصيات CSS في JavaScript، وهذا ضروريٌ لأنَّ JavaScript لا تسمح باستخدام الشرطات – في أسماء الخاصيات.
	</p>

	<p>
		عند تحويل شيفرة JSX السابقة باستخدام Babel، ثم تفسيرها من محرِّك JavaScript فستكون شيفرة HTML الناتجة:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_37" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="pln">color</span><span class="pun">:</span><span class="pln">red</span><span class="pun">;</span><span class="pln">background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln">black</span><span class="pun">;</span><span class="pln">font</span><span class="pun">-</span><span class="pln">weight</span><span class="pun">:</span><span class="pln">bold</span><span class="pun">;</span><span class="atv">"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">test</span><span class="tag">&lt;/div&gt;</span></pre>

	<h3>
		ملاحظات
	</h3>

	<ul>
<li>
			<p>
				يجب أن تبدأ السابقات الخاصة بالمتصفحات (باستثناء <code>ms</code>) بحرفٍ كبير، لهذا السبب تبدأ الخاصية <code>WebkitTransition</code> بحرف <code>W</code> كبير.
			</p>
		</li>
		<li>
			<p>
				يجب ألا يفاجئك استخدام الأحرف الكبيرة في أسماء خاصيات CSS بدلًا من الشرطات، فهذه هي الطريقة المتبعة للوصول إلى تلك الخاصيات في شجرة DOM عبر JavaScript (كما في <code>document.body.style.backgroundImage</code>).
			</p>
		</li>
		<li>
			<p>
				عند تحديد قيمة بواحدة البكسل، فستضيف React السلسلة النصية <code>"px"</code> تلقائيًا بعد القيم الرقمية باستثناء الخاصيات الآتية:
			</p>
		</li>
	</ul>
<pre class="ipsCode">
columnCount fillOpacity flex flexGrow flexShrink fontWeight lineClamp lineHeight
opacity order orphans strokeOpacity widows zIndex zoom
</pre>

	<h2>
		تعريف الخاصيات في JSX
	</h2>

	<p>
		في <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-r776/" rel="">المقال السابق</a>، ناقشنا تمرير خاصيات إلى الدالة <code>React.createElement(type, props, children)</code>‎ عند إنشاء عقد React. ولمّا كانت صيغة JSX ستحوِّل إلى استدعاءات للدالة <code>React.createElement()</code>‎ فأنت تملك فكرةً (من المقال السابق) كيف تعمل خاصيات React. لكن لمّا كانت JSX تُستخدَم للتعبير عن عناصر HTML فإنَّ الخاصيات المُعرَّفة ستُضاف إلى عنصر HTML الناتج.
	</p>

	<p>
		في المثال الآتي سأعرِّف عقدة <code>&lt;li&gt;</code> في React باستخدام JSX، ولها خمس خاصيات، لاحظ أنَّ إحداها هي خاصيةٌ غيرُ قياسيةٍ في HTML (وهي <code>foo: 'bar'</code>‎) أما البقية فهي خاصيات HTML عادية:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_39" style="">
<span class="kwd">var</span><span class="pln"> styles </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">backgroundColor</span><span class="pun">:</span><span class="str">'red'</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> tested </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> text </span><span class="pun">=</span><span class="pln"> </span><span class="str">'text'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">li id</span><span class="pun">=</span><span class="str">""</span><span class="pln">
                      data</span><span class="pun">-</span><span class="pln">test</span><span class="pun">={</span><span class="pln">tested</span><span class="pun">?</span><span class="str">'test'</span><span class="pun">:</span><span class="str">'false'</span><span class="pun">}</span><span class="pln">
                      className</span><span class="pun">=</span><span class="str">"blue"</span><span class="pln">
                      aria</span><span class="pun">-</span><span class="pln">test</span><span class="pun">=</span><span class="str">"test"</span><span class="pln">
                      style</span><span class="pun">={</span><span class="pln">styles</span><span class="pun">}</span><span class="pln">
                      foo</span><span class="pun">=</span><span class="str">"bar"</span><span class="pun">&gt;</span><span class="pln">
                          </span><span class="pun">{</span><span class="pln">text</span><span class="pun">}</span><span class="pln">
                  </span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNodeLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span></pre>

	<p>
		ستبدو شيفرة JSX بعد تحويلها كما يلي، لاحظي أنَّ الخاصيات أصبح وسائط مُمرَّرة إلى الدالة:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_41" style="">
<span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'li'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'data-test'</span><span class="pun">:</span><span class="pln"> tested </span><span class="pun">?</span><span class="pln"> </span><span class="str">'test'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">'false'</span><span class="pun">,</span><span class="pln">
        className</span><span class="pun">:</span><span class="pln"> </span><span class="str">'blue'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'aria-test'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">,</span><span class="pln">
        style</span><span class="pun">:</span><span class="pln"> styles</span><span class="pun">,</span><span class="pln">
        foo</span><span class="pun">:</span><span class="pln"> </span><span class="str">'bar'</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
    text
</span><span class="pun">);</span></pre>

	<p>
		عند تصيير العقد <code>reactNodeLi</code> إلى DOM، فستبدو كما يلي:
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2576_43" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app1"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"true"</span><span class="pln">
        </span><span class="atn">data-test</span><span class="pun">=</span><span class="atv">"test"</span><span class="pln">
        </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"blue"</span><span class="pln">
        </span><span class="atn">aria-test</span><span class="pun">=</span><span class="atv">"test"</span><span class="pln">
        </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="pln">background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln">red</span><span class="pun">;</span><span class="atv">"</span><span class="pln">
        </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">
            text
    </span><span class="tag">&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

	<p>
		يجب أن تلاحظ الأمور الأربعة الآتية:
	</p>

	<ul>
<li>
			<p>
				ترك قيمة إحدى الخاصيات فارغةً سيؤدي إلى جعل قيمتها مساويةً إلى <code>true</code> (أي <code>id=""‎</code> ستصبح <code>id="true"</code>‎، و <code>test</code> ستصبح <code>test="true"‎</code>).
			</p>
		</li>
		<li>
			<p>
				الخاصية <code>foo</code> لن تُضاف إلى العنصر النهائي لأنها ليست خاصية HTML قياسية.
			</p>
		</li>
		<li>
			<p>
				لا يمكنك كتابة أنماط سطرية في JSX. عليك أن تُشير إلى كائنٍ يقطع في مجال تعريف شيفرة JSX أو تمرير كائن يحتوي على خاصيات CSS مكتوبةً كخاصيات JavaScript.
			</p>
		</li>
		<li>
			<p>
				يمكن أن تُضاف قيم JavaScript ضمن JSX باستخدام القوسين المعقوفين <code>{}</code> (كما في <code>test={text}</code>‎ و <code>data-test={tested?'test':'false'}</code>‎).
			</p>
		</li>
	</ul>
<h3>
		ملاحظات
	</h3>

	<ul>
<li>
			<p>
				إذا كانت خاصيةٌ ما مكررةً فستؤخذ آخر قيمة لها.
			</p>
		</li>
		<li>
			<p>
				إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<code>&lt;x-my-component custom-attribute="foo" /&gt;</code>‎).
			</p>
		</li>
		<li>
			<p>
				الخاصية <code>class</code> يجب أن تكتب <code>className</code>.
			</p>
		</li>
		<li>
			<p>
				الخاصية <code>for</code> يجب أن تكتب <code>htmlFor</code>.
			</p>
		</li>
		<li>
			<p>
				الخاصية <code>style</code> تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي <code>background-color</code> تصبح <code>backgroundColor</code>).
			</p>
		</li>
		<li>
			<p>
				خاصيات النماذج في HTML (مثل <code>&lt;input&gt;</code> أو <code>&lt;textarea&gt;&lt;/textarea&gt;</code> …إلخ.) المُنشَأة كعقد React ستدعم خاصيات التي يمكن تغييرها عبر تفاعل المستخدم مع العنصر؛ وهذه الخاصيات هي <code>value</code> و <code>checked</code> و <code>selected</code>.
			</p>
		</li>
		<li>
			<p>
				توفِّر React الخاصيات <code>key</code> و <code><a href="https://wiki.hsoub.com/React/refs_and_the_dom" rel="external">ref</a></code> و <code><a href="https://wiki.hsoub.com/React/dom_elements#dangerouslySetInnerHTML" rel="external">dangerouslySetInnerHTML</a></code> التي لا تتوافر في DOM وتأخذ دورًا فريدًا.
			</p>
		</li>
		<li>
			<p>
				يجب أن تكتب جميع الخاصيات مع حذف الشرطة - وجعل أول حرف يليها مكتوبًا بحرفٍ كبير، أي أنَّ الخاصية <code>accept-charset</code> ستُكتَب <code>acceptCharset</code>.
			</p>
		</li>
		<li>
			<p>
				هذه هي خاصيات HTML التي تدعمها تطبيقات React:
			</p>
		</li>
	</ul>
<pre class="ipsCode">
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap
</pre>

	<h2>
		تعريف الأحداث في JSX
	</h2>

	<p>
		في <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-r776/" rel="">المقال السابق</a>، شرحنا ووضحنا كيف يمكن أن ترتبط الأحدث مع عقد React. لفعل المثل في JSX عليك إضافة الأحداث ودالة المعالجة الخاصة بها كخاصية لشيفرة JSX التي تُمثِّل عقدة React.
	</p>

	<p>
		أُخِذ المثال الآتي من المقال السابق ويبيّن طريقة إضافة حدث إلى عقدة React دون استخدام JSX:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_47" style="">
<span class="kwd">var</span><span class="pln"> mouseOverHandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> mouseOverHandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you moused over'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> clickhandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> clickhandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you clicked'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
        </span><span class="str">'div'</span><span class="pun">,</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> onClick</span><span class="pun">:</span><span class="pln"> clickhandler</span><span class="pun">,</span><span class="pln"> onMouseOver</span><span class="pun">:</span><span class="pln"> mouseOverHandler </span><span class="pun">},</span><span class="pln">
        </span><span class="str">'click or mouse over'</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

	<p>
		يمكن أن تُكتَب الشيفرة السابقة باستخدام JSX:
	</p>

	<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2576_49" style="">
<span class="kwd">var</span><span class="pln"> mouseOverHandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> mouseOverHandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you moused over'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> clickHandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> clickhandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you clicked'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div onClick</span><span class="pun">={</span><span class="pln">clickHandler</span><span class="pun">}</span><span class="pln"> onMouseOver</span><span class="pun">={</span><span class="pln">mouseOverHandler</span><span class="pun">}</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">click or mouse over</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

	<p>
		لاحظ أننا استخدمنا القوسين {} لربط دالة JavaScript إلى الحدث (أي onMouseOver={mouseOverHandler}‎)، وهذه الطريقة تشابه طريقة ربط الأحداث السطرية في DOM.
	</p>

	<p>
		الأحداث التي تدعمها React موجودةٌ في الجدول الآتي:
	</p>

	<table>
<thead><tr>
<th>
					نوع الحدث
				</th>
				<th>
					الأحداث
				</th>
				<th>
					خاصيات متعلقة به
				</th>
			</tr></thead>
<tbody>
<tr>
<td>
					الحافظة
				</td>
				<td>
					<ul>
<li>
							<code>onCopy</code>
						</li>
						<li>
							<code>onCut</code>
						</li>
						<li>
							<code>onPaste</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>DOMDataTransfer</code>
						</li>
						<li>
							<code>clipboardData</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					التركيب
				</td>
				<td>
					<ul>
<li>
							<code>onCompositionEnd</code>
						</li>
						<li>
							<code>onCompositionStart</code>
						</li>
						<li>
							<code>onCompositionUpdate</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>data</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						لوحة المفاتيح
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onKeyDown</code>
						</li>
						<li>
							<code>onKeyPress</code>
						</li>
						<li>
							<code>onKeyUp</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>altKey</code>
						</li>
						<li>
							<code>charCode</code>
						</li>
						<li>
							<code>ctrlKey</code>
						</li>
						<li>
							<code>getModifierState(key)‎</code>
						</li>
						<li>
							<code>key</code>
						</li>
						<li>
							<code>keyCode</code>
						</li>
						<li>
							<code>locale</code>
						</li>
						<li>
							<code>location</code>
						</li>
						<li>
							<code>metaKey</code>
						</li>
						<li>
							<code>repeat</code>
						</li>
						<li>
							<code>shiftKey</code>
						</li>
						<li>
							<code>which</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						التركيز
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onChange</code>
						</li>
						<li>
							<code>onInput</code>
						</li>
						<li>
							<code>onSubmit</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>DOMEventTarget</code>
						</li>
						<li>
							<code>relatedTarget</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						النماذج
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>OnFocus</code>
						</li>
						<li>
							<code>onBlur</code>
						</li>
					</ul>
</td>
				<td>
					<p>
						 
					</p>
				</td>
			</tr>
<tr>
<td>
					<p>
						الفأرة
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onClick</code>
						</li>
						<li>
							<code>onContextMenu</code>
						</li>
						<li>
							<code>onDoubleClick</code>
						</li>
						<li>
							<code>onDrag</code>
						</li>
						<li>
							<code>onDragEnd</code>
						</li>
						<li>
							<code>onDragEnter</code>
						</li>
						<li>
							<code>onDragExit</code>
						</li>
						<li>
							<code>onDragLeave</code>
						</li>
						<li>
							<code>onDragOver</code>
						</li>
						<li>
							<code>onDragStart</code>
						</li>
						<li>
							<code>onDrop</code>
						</li>
						<li>
							<code>onMouseDown</code>
						</li>
						<li>
							<code>onMouseEnter</code>
						</li>
						<li>
							<code>onMouseLeave</code>
						</li>
						<li>
							<code>onMouseMove</code>
						</li>
						<li>
							<code>onMouseOut</code>
						</li>
						<li>
							<code>onMouseOver</code>
						</li>
						<li>
							<code>onMouseUp</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>altKey</code>
						</li>
						<li>
							<code>button</code>
						</li>
						<li>
							<code>buttons</code>
						</li>
						<li>
							<code>clientX</code>
						</li>
						<li>
							<code>clientY</code>
						</li>
						<li>
							<code>ctrlKey</code>
						</li>
						<li>
							<code>getModifierState</code>(key)‎
						</li>
						<li>
							<code>metaKey</code>
						</li>
						<li>
							<code>pageX</code>
						</li>
						<li>
							<code>pageY</code>
						</li>
						<li>
							<code>DOMEventTarget</code>
						</li>
						<li>
							<code>relatedTarget</code>
						</li>
						<li>
							<code>screenX</code>
						</li>
						<li>
							<code>screenY</code>
						</li>
						<li>
							<code>shiftKey</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						الاختيار
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onSelect</code>
						</li>
					</ul>
</td>
				<td>
					<p>
						 
					</p>
				</td>
			</tr>
<tr>
<td>
					<p>
						اللمس
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onTouchCancel</code>
						</li>
						<li>
							<code>onTouchEnd</code>
						</li>
						<li>
							<code>onTouchMove</code>
						</li>
						<li>
							<code>onTouchStart</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>altKey</code>
						</li>
						<li>
							<code>DOMTouchList</code>
						</li>
						<li>
							<code>changedTouches</code>
						</li>
						<li>
							<code>ctrlKey</code>
						</li>
						<li>
							<code>getModifierState(key)‎</code>
						</li>
						<li>
							<code>metaKey</code>
						</li>
						<li>
							<code>shiftKey</code>
						</li>
						<li>
							<code>DOMTouchList</code>
						</li>
						<li>
							<code>targetTouches</code>
						</li>
						<li>
							<code>DOMTouchList</code>
						</li>
						<li>
							<code>touches</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						واجهة المستخدم
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onScroll</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>detail</code>
						</li>
						<li>
							<code>DOMAbstractView</code>
						</li>
						<li>
							<code>view</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						الدولاب
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onWheel</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>deltaMode</code>
						</li>
						<li>
							<code>deltaX</code>
						</li>
						<li>
							<code>deltaY</code>
						</li>
						<li>
							<code>deltaZ</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						الوسائط
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onAbort</code>
						</li>
						<li>
							<code>onCanPlay</code>
						</li>
						<li>
							<code>onCanPlayThrough</code>
						</li>
						<li>
							<code>onDurationChange</code>
						</li>
						<li>
							<code>onEmptied</code>
						</li>
						<li>
							<code>onEncrypted</code>
						</li>
						<li>
							<code>onEnded</code>
						</li>
						<li>
							<code>onError</code>
						</li>
						<li>
							<code>onLoadedData</code>
						</li>
						<li>
							<code>onLoadedMetadata</code>
						</li>
						<li>
							<code>onLoadStart</code>
						</li>
						<li>
							<code>onPause</code>
						</li>
						<li>
							<code>onPlay</code>
						</li>
						<li>
							<code>onPlaying</code>
						</li>
						<li>
							<code>onProgress</code>
						</li>
						<li>
							<code>onRateChange</code>
						</li>
						<li>
							<code>onSeeked</code>
						</li>
						<li>
							<code>onSeeking</code>
						</li>
						<li>
							<code>onStalled</code>
						</li>
						<li>
							<code>onSuspend</code>
						</li>
						<li>
							<code>onTimeUpdate</code>
						</li>
						<li>
							<code>onVolumeChange</code>
						</li>
						<li>
							<code>onWaiting</code>
						</li>
					</ul>
</td>
				<td>
					<p>
						 
					</p>

					<ul></ul>
</td>
			</tr>
<tr>
<td>
					<p>
						الصور
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onLoad</code>
						</li>
						<li>
							<code>onError</code>
						</li>
					</ul>
</td>
				<td>
					<p>
						 
					</p>
				</td>
			</tr>
<tr>
<td>
					<p>
						الحركات
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onAnimationStart</code>
						</li>
						<li>
							<code>onAnimationEnd</code>
						</li>
						<li>
							<code>onAnimationIteration</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>animationName</code>
						</li>
						<li>
							<code>pseudoElement</code>
						</li>
						<li>
							<code>elapsedTime</code>
						</li>
					</ul>
</td>
			</tr>
<tr>
<td>
					<p>
						الانتقالات
					</p>
				</td>
				<td>
					<ul>
<li>
							<code>onTransitionEnd</code>
						</li>
					</ul>
</td>
				<td>
					<ul>
<li>
							<code>propertyName</code>
						</li>
						<li>
							<code>pseudoElement</code>
						</li>
						<li>
							<code>elapsedTime</code>
						</li>
					</ul>
</td>
			</tr>
</tbody>
</table>
<h3>
		ملاحظات
	</h3>

	<ul>
<li>
			<p>
				توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات.
			</p>
		</li>
		<li>
			<p>
				تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة <code>"Capture"</code> إلى اسم الحدث، أي أنَّ الحدث <code>onClick</code> سيصبح <code>onClickCapture</code>).
			</p>
		</li>
		<li>
			<p>
				إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية <code>nativeEvent</code> في كائن <code>SyntheticEvent</code> المُمرَّر إلى دالة معالجة الأحداث في React.
			</p>
		</li>
		<li>
			<p>
				لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation).
			</p>
		</li>
		<li>
			<p>
				يجب استخدام <code>e.stopPropagation()‎</code> أو <code>e.preventDefault()</code>‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام <code>return false;‎</code>.
			</p>
		</li>
		<li>
			<p>
				لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام <a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">توابع دورة الحياة</a> في React.
			</p>
		</li>
	</ul>
<p>
		ترجمة وبتصرف للفصل <a href="https://www.reactenlightenment.com/react-jsx.html" rel="external nofollow">JavaScript Syntax Extension (a.k.a, JSX)</a>‎ من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
	</p>
</div>
]]></description><guid isPermaLink="false">777</guid><pubDate>Wed, 22 Jan 2020 13:00:00 +0000</pubDate></item><item><title>&#x639;&#x642;&#x62F; React Nodes) React)</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%B9%D9%82%D8%AF-react-nodes-react-r776/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e1639271d6c8___React_4.jpg.f8b72817c19752e8ba5b8f3485ae7f5f.jpg" /></p>

<p>
	سيناقش هذا المقال إنشاء عقد React ‏(React Nodes) سواءً النصية (text nodes) أو عقد العناصر (element nodes) باستخدام JavaScript.
</p>

<h2>
	ما هي عقدة React؟
</h2>

<p>
	النوع الأساسي أو القيمة التي تُنشَأ عند استخدام مكتبة React تسمى «عقدة React»، ويمكن تعريف عقدة React على أنها «تمثيل افتراضي خفيف وعديم الحالة وغير قابلٍ للتعديل لعقدة DOM» (لا تخف من الكلام السابق، هذا هو التعريف الرسمي، ما باليد حيلة :-) ).
</p>

<p>
	عقد React ليست عقد DOM حقيقية، وإنما تمثيل عن عقدة DOM محتملة، وهذا التمثيل يعد على أنه شجرة DOM افتراضية، ويُستخدم React لتعريف شجرة DOM الافتراضية باستخدام عقد React، والتي تُشكِّل البنية الأساسية لمكوِّنات React، والتي في نهاية المطاف ستُستخدَم لإنشاء بنية DOM الحقيقة وغير ذلك من البنى (مثل <a href="https://wiki.hsoub.com/ReactNative" rel="external">React Native</a>).
</p>

<p>
	يمكن أن تُنشَأ عقد React باستخدام JSX أو JavaScript. سنلقي في هذا المقال نظرةً على إنشاء عقد React باستخدام JavaScript بمفردها دون استخدام JSX. إذ أرى أنَّ عليك فهم ما الذي تخفيه JSX وراء الكواليس لكي تفهم JSX فهمًا جيدًا.
</p>

<p>
	قد تحدثك نفسك بتجاوز هذا المقال لأنك تعرف مسبقًا أننا لن نستخدم JSX. لا تطعها! أقترح عليك أن تكمل قراءة هذا المقال لكي تعرف ما الذي تفعله لك JSX. ربما هذا أهم مقال في السلسلة ليتغلغل في ذهنك!
</p>

<h2>
	إنشاء عقد العناصر
</h2>

<p>
	سيُفضِّل المطورون في أغلبية الأوقات استخدام JSX مع React لإنشاء عقد العناصر، وبغض النظر عن ذلك، سنتعرّف في هذا المقال على طريقة إنشاء عقد React دون استخدام JSX باستعمال JavaScript فقط. أما <a href="https://academy.hsoub.com/programming/javascript/react/%D8%B5%D9%8A%D8%BA%D8%A9-jsx-javascript-syntax-extension-r777/" rel="">المقال القادم</a> فهو يناقش كيفية إنشاء عقد React باستخدام JSX.
</p>

<p>
	إنشاء عقد React سهلٌ جدًا فكل ما نحتاج له هو استخدام الدالة React.createElement(type, props, children)‎ وتمرير مجموعة من الوسائط إليها والتي تُعرِّف عقدة DOM الفعلية (مثالًا نضبط قيمة type إلى عنصر من عناصر HTML مثل <code>&lt;li&gt;</code> أو عنصر مخصص مثل <code>&lt;my-li&gt;</code>).
</p>

<p>
	وسائط الدالة <code><a href="https://wiki.hsoub.com/React/react_api#createElement.28.29.E2.80.8E" rel="external">React.createElement()</a>)‎</code> مشروحة أدناه:
</p>

<ul>
<li>
		<p>
			<code>type (string | React.createClass())</code>‎<br>
			يمكن أن تكون سلسلة نصية تُمثِّل عنصر HTML (أو عنصر HTML مخصص) أو نسخة من مكوِّنات React.
		</p>
	</li>
	<li>
		<p>
			<code>props (null | object)</code>‎<br>
			يمكن أن يكون <code><a href="https://wiki.hsoub.com/JavaScript/null" rel="external">null</a></code> أو كائن يحتوي على خاصيات وقيم مرتبطة بها.
		</p>
	</li>
	<li>
		<p>
			<code>children (null | string | React.Component | React.createElement())</code>‎<br>
			يمكن أن تكون <code>null</code> أو سلسلة نصية التي ستحوّل إلى عقدة نصية، أو نسخة من <code>React.Component</code>‎ أو <code>React.createElement()</code>‎.
		</p>
	</li>
</ul>
<p>
	سأستخدم في المثال الآتي الدالة <code>React.createElement()</code>‎ لإنشاء تمثيل في شجرة DOM الافتراضية لعقدة العنصر <code><a href="https://wiki.hsoub.com/HTML/li" rel="external">&lt;li&gt;</a></code> والتي تحتوي على عقدة نصية فيها <code>one</code> (أي عقدة نصية في React) ومُعرِّف <code>id</code> يساوي <code>li1</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_10" style="">
<span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="str">'li1'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'one'</span><span class="pun">);</span></pre>

<p>
	لاحظ أنَّ أول وسيط يُعرِّف ما هو عنصر HTML الذي نريد تمثيله، ويعُرِّف الوسيط الثاني ما هي الخاصيات التي ستُضبَط على العناصر <code>&lt;li&gt;</code>، وأخيرًا سيُعرِّف الوسيط الثالث ما هي العقدة الموجودة داخل العنصر، وفي هذه الحالة وضعنا ببساطة عقدةً نصية (أي <code>'one'</code>) داخل <code>&lt;li&gt;</code>. لاحظ أنَّ آخر وسيط الذي سيصبح ابنًا للعقدة المُنشَأة يمكن أن يكون عقدة React نصية، أو عقدة عنصر في React، أو نسخة من مكوِّن React.
</p>

<p>
	كل ما فعلناه إلى الآن هو إنشاء عقدة عنصر في React تحتوي على عقدة React نصية، والتي خزناها في المتغير <code>reactNodeLi</code>، ولإنشاء شجرة DOM الوهمية فعلينا تصيير عقدة عنصر React في شجرة DOM الحقيقية، ولفعل ذلك سنستخدم الدالة <code>ReactDOM.render()</code>‎:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_12" style="">
<span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNodeLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	إذا أردنا وصف الشيفرة السابقة ببساطة، فهي تتضمن:
</p>

<ol>
<li>
		<p>
			إنشاء شجرة DOM افتراضية مبنية من عقدة عنصر React المُمرَّرة (أي <code>reactNodeLi</code>)،
		</p>
	</li>
	<li>
		<p>
			استخدام شجرة DOM الافتراضية لإعادة إنشاء فرع من شجرة DOM الحقيقية،
		</p>
	</li>
	<li>
		<p>
			إضافة الفرع المُنشَأ (أي <code>&lt;li id="li1"&gt;one&lt;/li&gt;</code>) إلى شجرة DOM الحقيقة كأحد أبناء العنصر <code>&lt;div id="app"&gt;&lt;/div&gt;</code>.
		</p>
	</li>
</ol>
<p>
	بعبارةٍ أخرى، ستتغير شجرة DOM لمستند HTML من:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3822_14" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;&lt;/div&gt;</span></pre>

<p>
	إلى:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9133_8" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;</span><span class="pln">
    // data-reactid قد أضافت الخاصية React لاحظ أنَّ  
    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"li1"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">one</span><span class="tag">&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	بيّن المثال السابق استخدامًا بسيطًا للدالة <code>React.createElement()‎</code>. يمكن للدالة <code>React.createElement()‎</code> إنشاء بنى معقدة أيضًا. فعلى سبيل المثال سنستخدم الدالة <code>React.createElement()‎</code> لإنشاء فرع من عقد React يُمثِّل قائمة غير مرتبة من العناصر (أي <code><a href="https://wiki.hsoub.com/HTML/ul" rel="external">&lt;ul&gt;</a></code>):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9133_10" style="">
<span class="com">// React في &lt;li&gt; إنشاء عقد عناصر</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> rElmLi1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="str">'li1'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'one'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> rElmLi2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="str">'li2'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'two'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> rElmLi3 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="str">'li3'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'three'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// السابقة إليها &lt;li&gt; وإضافة عناصر React في &lt;ul&gt; إنشاء عقدة العنصر</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactElementUl </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'ul'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">className</span><span class="pun">:</span><span class="pln"> </span><span class="str">'myList'</span><span class="pun">},</span><span class="pln"> rElmLi1</span><span class="pun">,</span><span class="pln"> rElmLi2</span><span class="pun">,</span><span class="pln"> rElmLi3</span><span class="pun">);</span></pre>

<p>
	قبل تصيير القائمة غير المرتبة إلى شجرة DOM، أرى إخبارك أنَّه يمكن تبسيط الشيفرة السابقة باستخدام <code>React.createElement()</code>‎ بدلًا من المتغيرات. هذا المثال يوضِّح كيف يمكن تعريف الهيكلية باستخدام JavaScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_21" style="">
<span class="kwd">var</span><span class="pln"> reactElementUl </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
    </span><span class="str">'ul'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        className</span><span class="pun">:</span><span class="pln"> </span><span class="str">'myList'</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
        </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="pln"> </span><span class="str">'li1'</span><span class="pun">},</span><span class="str">'one'</span><span class="pun">),</span><span class="pln">
        </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="pln"> </span><span class="str">'li2'</span><span class="pun">},</span><span class="str">'two'</span><span class="pun">),</span><span class="pln">
        </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">id</span><span class="pun">:</span><span class="pln"> </span><span class="str">'li3'</span><span class="pun">},</span><span class="str">'three'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	عند تصيير الشيفرة السابقة إلى DOM فستبدو شيفرة HTML الناتجة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3822_23" style="">
<span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"myList"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"li1"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.0"</span><span class="tag">&gt;</span><span class="pln">one</span><span class="tag">&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"li2"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.1"</span><span class="tag">&gt;</span><span class="pln">two</span><span class="tag">&lt;/li&gt;</span><span class="pln">
    </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"li3"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0.2"</span><span class="tag">&gt;</span><span class="pln">three</span><span class="tag">&lt;/li&gt;</span><span class="pln">
</span><span class="tag">&lt;/ul&gt;</span></pre>

<p>
	يجب أن يكون واضحًا أنَّ عقد React هي كائنات JavaScript في شجرةٍ تمثِّل عقد DOM حقيقية داخل شجرة DOM الافتراضية. ثم تُستخدَم شجرة DOM الافتراضية لتعديل شجرة DOM الحقيقية داخل صفحة HTML.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			يمكن أن يكون الوسيط <code>type</code> المُمرَّر إلى الدالة <code>React.createElement()‎</code> سلسلةً نصية تُشير إلى عنصر من عناصر HTML القياسية (مثل <code>'li'</code> الذي يمُثِّل العنصر <code>&lt;li&gt;</code>)، أو عنصرًا مخصصًا (مثل <code>'foo-bar'</code> الذي يُمثِّل العنصر <code>&lt;foo-bar&gt;</code>)، أو نسخة من مكوِّن في React (أي نسخة من <code>React.Component</code>).
		</p>
	</li>
	<li>
		<p>
			هذه هي قائمة عناصر HTML التي تدعمها React (أي تمرير هذه العناصر كسلسلة نصية مكان المعامل type إلى الدالة <code>createElement()</code>‎ سيؤدي إلى إنشاء عنصر HTML القياسي في DOM):
		</p>
	</li>
</ul>
<pre class="ipsCode">
a abbr address area article aside audio b base bdi bdo big blockquote body br
button canvas caption cite code col colgroup data datalist dd del details dfn
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
link main map mark menu menuitem meta meter nav noscript object ol optgroup
option output p param picture pre progress q rp rt ruby s samp script section
select small source span strong style sub summary sup table tbody td textarea
tfoot th thead time title tr track u ul var video wbr
</pre>

<h2>
	تصيير (rendering) العناصر إلى شجرة DOM
</h2>

<p>
	توفِّر React الدالة <code>React.render()</code>‎ من الملف <code>react-dom.js</code> التي يمكن أن تُستخدَم لتصيير عقد عناصر React إلى شجرة DOM. لقد رأينا الدالة <code>render()</code>‎ مستخدمةً في هذا المقال.
</p>

<p>
	سنستخدم في المثال الآتي الدالة <code>ReactDOM.render()</code>‎ وستُصيّر عقد العناصر <code>'&lt;li&gt;'</code> و <code>'&lt;foo-bar&gt;'</code> إلى شجرة DOM:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9133_12" style="">
<span class="com">// حقيقي DOM والتي تُمثِّل عقدة عنصر React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLLi</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">className</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مخصص HTML والتي تُمثِّل عقد عنصر React عقدة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HTMLCustom</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'foo-bar'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">className</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'foo'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// &lt;div id="app1"&gt;&lt;/div&gt; إلى HTMLLi تصيير عقدة العنصر   </span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span><span class="pln">

</span><span class="com">// &lt;div id="app2"&gt;&lt;/div&gt; إلى HTMLCustom تصيير عقدة العنصر   </span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">HTMLCustom</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app2'</span><span class="pun">));</span></pre>

<p>
	بعد تصيير العناصر إلى شجرة DOM، فسيبدو مستند HTML المُحدَّث كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3822_27" style="">
<span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app1"</span><span class="tag">&gt;&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/li&gt;&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app2"</span><span class="tag">&gt;&lt;foo-bar</span><span class="pln"> </span><span class="atn">classname</span><span class="pun">=</span><span class="atv">"bar"</span><span class="pln"> </span><span class="atn">children</span><span class="pun">=</span><span class="atv">"foo"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".1"</span><span class="tag">&gt;</span><span class="pln">foo</span><span class="tag">&lt;/foo-bar&gt;&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	الدالة <code>ReactDOM.render()</code>‎ هي الطريقة المبدئية التي تمكننا من نقل عقد العناصر في React إلى شجرة DOM الوهمية، ثم إلى شجرة DOM الحقيقية.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			ستستبدل أي عقد DOM داخل عناصر DOM التي سيُصيَّر إليها (أي أنها ستُحذَف ويحلّ المحتوى الجديد محلها).
		</p>
	</li>
	<li>
		<p>
			الدالة <code>ReactDOM.render()‎</code> لا تعدِّل عقدة عنصر DOM الذي تُصيّر React إليه، وإنما تتطلَّب React ملكيةً كاملةً للعقدة النصية عند التصيير، فلا يجدر بك إضافة أبناء أو إزالة أبناء من العقدة التي تضيف React فيها المكوِّن أو العقدة.
		</p>
	</li>
	<li>
		<p>
			التصيير إلى شجرة HTML DOM هو أحد الخيارات فقط، فهنالك <a href="https://wiki.hsoub.com/React/react_dom_server" rel="external">خياراتٌ أخرى ممكنة</a>، فمثلًا تستطيع التصيير إلى سلسلة نصية (أي <code><a href="https://wiki.hsoub.com/React/react_dom_server#renderToString.28.29.E2.80.8E" rel="external">ReactDOMServer.renderToString()</a></code>‎) في جهة الخادم.
		</p>
	</li>
	<li>
		<p>
			إعادة تصيير نفس عنصر DOM سيؤدي إلى تحديث العقد الأبناء الحاليين إذا حدث تغييرٌ فيها، أو إذا أُضيفت عقدة عنصر ابن جديدة.
		</p>
	</li>
</ul>
<h2>
	تعريف خاصيات العقد
</h2>

<p>
	الوسيط الثاني الذي يُمرَّر إلى الدالة <code>React.createElement(type, props, children)</code>‎ هو كائنٌ يحتوي على خاصيات ذات أسماء ترتبط بها قيم.
</p>

<p>
	تمتلك الخاصيات عدِّة أدوار:
</p>

<ol>
<li>
		<p>
			يمكن أن تتحول إلى خاصيات HTML. فلو طابقت إحدى الخاصيات خاصية HTML معروفة، فستُضاف إلى عنصر HTML النهائي في DOM.
		</p>
	</li>
	<li>
		<p>
			الخاصيات المُمرَّرة إلى <code>createElement()</code>‎ ستصبح قيمًا مخزنةً في الكائن <code>prop</code> كنسخة من <code>React.createElement()</code>‎ (أي ‎<code>[INSTANCE].props.[NAME_OF_PROP]</code>). تستخدم الخاصيات بكثرة لإدخال قيم إلى المكوِّنات.
		</p>
	</li>
	<li>
		<p>
			تمتلك بعض الخاصيات تأثيراتٍ جانبية (مثل <code>key</code> و <code><a href="https://wiki.hsoub.com/React/refs_and_the_dom" rel="external">ref</a></code> و <code><a href="https://wiki.hsoub.com/React/dom_elements#dangerouslySetInnerHTML" rel="external">dangerouslySetInnerHTML</a></code>).
		</p>
	</li>
</ol>
<p>
	يمكنك أن تتخيل الخاصيات على أنها خيارات ضبط لعقد React، ويمكنك أن تتخيلها كخاصيات HTML.
</p>

<p>
	سنُعرِّف في المثال الآتي عقدة العنصر <code>&lt;li&gt;</code> مع خمس خاصيات، إحدى تلك الخاصيات غير قياسية في HTML (أقصد بها <code>foo:'bar'</code>‎) وبقية الخاصيات معروفة في HTML:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9133_14" style="">
<span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">,</span><span class="pln">
    id</span><span class="pun">:</span><span class="str">'li1'</span><span class="pun">,</span><span class="pln">
    </span><span class="com">// للإشارة إلى صنف الأنماط في جافاسكربت className لاحظ استخدام الخاصية </span><span class="pln">
    className</span><span class="pun">:</span><span class="pln"> </span><span class="str">'blue'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'data-test'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'aria-test'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">,</span><span class="pln">
    </span><span class="com">// CSS لضبط خاصية backgroundColor لاحظ استخدام الخاصية</span><span class="pln">
    style</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">backgroundColor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'red'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">},</span><span class="pln">
</span><span class="str">'text'</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	ستبدو الشيفرة المُصيَّرة إلى صفحة HTML كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3822_34" style="">
<span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"li1"</span><span class="pln"> </span><span class="atn">data-test</span><span class="pun">=</span><span class="atv">"test"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"blue"</span><span class="pln"> </span><span class="atn">aria-test</span><span class="pun">=</span><span class="atv">"test"</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="pln">background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln">red</span><span class="pun">;</span><span class="atv">"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">text</span><span class="tag">&lt;/li&gt;</span></pre>

<p>
	ما عليك إدراكه من المثال السابق أنَّ خاصيات HTML القياسية فقط، وخاصيات <code>data-*</code>‎ و <code>aria-*</code>‎ هي الخاصيات الوحيدة التي تنتقل إلى شجرة DOM الحقيقية من شجرة DOM الافتراضية.
</p>

<p>
	لاحظ أنَّ الخاصية <code>foo</code> لن تظهر في شجرة DOM الحقيقية، فهذه الخاصية غير القياسية ستكون متاحةً في نسخة الكائن <code>li</code> لعقدة React (أي <code>reactNodeLi.props.foo</code>):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_36" style="">
<span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,{</span><span class="pln">
    foo</span><span class="pun">:</span><span class="str">'bar'</span><span class="pun">,</span><span class="pln">
    id</span><span class="pun">:</span><span class="str">'li1'</span><span class="pun">,</span><span class="pln">
    className</span><span class="pun">:</span><span class="pln"> </span><span class="str">'blue'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'data-test'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'aria-test'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">,</span><span class="pln">
    style</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">backgroundColor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'red'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">},</span><span class="pln">
</span><span class="str">'text'</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">reactNodeLi</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">);</span><span class="pln"> </span><span class="com">// bar</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNodeLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ليس استخدام خاصيات React مقتصرًا على تحويلها إلى خاصيات HTML حقيقية، لكن يمكن أن تلعب دورًا في إعدادات الضبط المُمرَّرة إلى مكونات React. هذا الجانب من جوانب استخدام الخاصيات سيغطى في مقالٍ خاصٍ به، أما الآن فكل ما علينا إدراكه هو أنَّ تمرير خاصية إلى عقدة React هو أمرٌ يختلف عن تعريف خاصية في مكوِّن لكي تُستخدم لمدخلات ضبط ضمن ذاك المكوِّن.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			ترك قيمة إحدى الخاصيات فارغةً سيؤدي إلى جعل قيمتها مساويةً إلى <code>true</code> (أي <code>id=""‎</code> ستصبح <code>id="true"</code>‎، و <code>test</code> ستصبح <code>test="true"‎</code>).
		</p>
	</li>
	<li>
		<p>
			إذا كانت خاصيةٌ ما مكررةً فستؤخذ آخر قيمة لها.
		</p>
	</li>
	<li>
		<p>
			إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<code>&lt;x-my-component custom-attribute="foo" /&gt;</code>‎).
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>class</code> يجب أن تكتب <code>className</code>.
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>for</code> يجب أن تكتب <code>htmlFor</code>.
		</p>
	</li>
	<li>
		<p>
			الخاصية <code>style</code> تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي <code>background-color</code> تصبح <code>backgroundColor</code>).
		</p>
	</li>
	<li>
		<p>
			خاصيات النماذج في HTML (مثل <code>&lt;input&gt;</code> أو <code>&lt;textarea&gt;&lt;/textarea&gt;</code> …إلخ.) المُنشَأة كعقد React ستدعم خاصيات التي يمكن تغييرها عبر تفاعل المستخدم مع العنصر؛ وهذه الخاصيات هي <code>value</code> و <code>checked</code> و <code>selected</code>.
		</p>
	</li>
	<li>
		<p>
			توفِّر React الخاصيات <code>key</code> و <code><a href="https://wiki.hsoub.com/React/refs_and_the_dom" rel="external">ref</a></code> و <code><a href="https://wiki.hsoub.com/React/dom_elements#dangerouslySetInnerHTML" rel="external">dangerouslySetInnerHTML</a>)</code> التي لا تتوافر في DOM وتأخذ دورًا فريدًا.
		</p>
	</li>
	<li>
		<p>
			يجب أن تكتب جميع الخاصيات مع حذف الشرطة - وجعل أول حرف يليها مكتوبًا بحرفٍ كبير، أي أنَّ الخاصية <code>accept-charset</code> ستُكتَب <code>acceptCharset</code>.
		</p>
	</li>
	<li>
		<p>
			هذه هي خاصيات HTML التي تدعمها تطبيقات React:
		</p>
	</li>
</ul>
<pre class="ipsCode">
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap
</pre>

<h2>
	تضمين أنماط CSS السطرية في عقد العناصر
</h2>

<p>
	لتطبيق أنماط CSS السطرية (inline CSS styles) على عقدة React، فعليك تمرير كائن يحتوي على خاصيات CSS والقيم المرتبطة بها إلى الخاصية style.
</p>

<p>
	على سبيل المثال، سنمرر مرجعيةً إلى الكائن <code>inlineStyles</code> إلى الخاصية <code>style</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_40" style="">
<span class="kwd">var</span><span class="pln"> inlineStyles </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">backgroundColor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'red'</span><span class="pun">,</span><span class="pln"> fontSize</span><span class="pun">:</span><span class="pln"> </span><span class="lit">20</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln">  </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">style</span><span class="pun">:</span><span class="pln"> inlineStyles</span><span class="pun">},</span><span class="pln"> </span><span class="str">'styled'</span><span class="pun">)</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNodeLi</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app1'</span><span class="pun">));</span></pre>

<p>
	ستبدو شيفرة HTML الناتجة شبيهةً بما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3822_42" style="">
<span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app1"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="pln">background</span><span class="pun">-</span><span class="pln">color</span><span class="pun">:</span><span class="pln">red</span><span class="pun">;</span><span class="pln">font</span><span class="pun">-</span><span class="pln">size</span><span class="pun">:</span><span class="lit">20px</span><span class="pun">;</span><span class="atv">"</span><span class="pln"> </span><span class="atn">data-reactid</span><span class="pun">=</span><span class="atv">".0"</span><span class="tag">&gt;</span><span class="pln">styled</span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	هنالك أمران عليك الانتباه إليهما في الشيفرة السابقة:
</p>

<ol>
<li>
		<p>
			لم نضف الواحدة <code>"px"</code> إلى الخاصية <code>fontSize</code> لأنَّ React أضافته عوضًا عنّا.
		</p>
	</li>
	<li>
		<p>
			عند كتابة خاصيات CSS في JavaScript، يجب حذف الشرطة وجعل الحرف الذي يليها مكتوبًا بحرفٍ كبير (أي <code>backgroundColor</code> بدلًا من <code>background-color</code>).
		</p>
	</li>
</ol>
<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			يجب أن تبدأ السابقات الخاصة بالمتصفحات (باستثناء <code>ms</code>) بحرفٍ كبير، لهذا السبب تبدأ الخاصية <code>WebkitTransition</code> بحرف <code>W</code> كبير (ولم أعد أنصح بإضافة هذه الخاصيات إلا لدعم المتصفحات القديمة جدًا).
		</p>
	</li>
	<li>
		<p>
			يجب ألا يفاجئك استخدام الأحرف الكبيرة في أسماء خاصيات CSS بدلًا من الشرطات، فهذه هي الطريقة المتبعة للوصول إلى تلك الخاصيات في شجرة DOM عبر JavaScript (كما في <code>document.body.style.backgroundImage</code>).
		</p>
	</li>
	<li>
		<p>
			عند تحديد قيمة بواحدة البكسل، فستضيف React السلسلة النصية <code>"px"</code> تلقائيًا بعد القيم الرقمية باستثناء الخاصيات الآتية:
		</p>
	</li>
</ul>
<pre class="ipsCode">
columnCount fillOpacity flex flexGrow flexShrink fontWeight lineClamp lineHeight
opacity order orphans strokeOpacity widows zIndex zoom
</pre>

<h2>
	استخدام مصانع العناصر المُضمَّنة في React
</h2>

<p>
	توفِّر React اختصارات مضمَّنة لإنشاء عقد عناصر HTML شائعة الاستخدام. تسمى هذه الاختصارات بمصانع عقد React.
</p>

<p>
	قبل الإصدار 16.0 من مكتبة React.js، كانت هذه المصانع مضمنة في المكتبة نفسها، لكن بعد الإصدار 16.0 فقد أسقط الدعم عنها، وظهرت وحدة باسم <code><a href="https://www.npmjs.com/package/react-dom-factories" rel="external nofollow">react-dom-factories</a>)</code> التي تتيح استخدام المصانع التي كانت مضمنة في React.js مع الإصدارات الجديدة من المكتبة.
</p>

<p>
	مصنع لعقد React هو دالةٌ تولِّد <code>ReactElement</code> مع قيمة معينة لخاصية type.
</p>

<p>
	باستخدام المصنع المضمن <code>React.DOM.li()</code>‎، يمكننا إنشاء عقدة العنصر <code>&lt;li&gt;one&lt;/li&gt;</code> في React كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_45" style="">
<span class="com">// DOM.li(props, children);</span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> DOM from </span><span class="str">'react-dom-factories'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> DOM</span><span class="pun">.</span><span class="pln">li</span><span class="pun">({</span><span class="pln">id</span><span class="pun">:</span><span class="str">'li1'</span><span class="pun">},</span><span class="pln"> </span><span class="str">'one'</span><span class="pun">);</span></pre>

<p>
	وذلك بدلًا من استخدام:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_47" style="">
<span class="com">// React.createElement(type, prop, children)</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNodeLi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'li'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> </span><span class="str">'one'</span><span class="pun">);</span></pre>

<p>
	هذه قائمة بجميع المصانع المُضمَّنة في React:
</p>

<pre class="ipsCode">
a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,big,blockquote,body,br,button,
canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,
dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,
hr,html,i,iframe,img,input,ins,kbd,keygen,label,legend,li,link,main,map,mark,menu,
menuitem,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture,
pre,progress,q,rp,rt,ruby,s,samp,script,section,select,small,source,span,strong,
style,sub,summary,sup,table,tbody,td,textarea,tfoot,th,thead,time,title,tr,track,
u,ul,var,video,wbr,circle,clipPath,defs,ellipse,g,image,line,linearGradient,mask,
path,pattern,polygon,polyline,radialGradient,rect,stop,svg,text,tspa
</pre>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			إذا كنتَ تستخدم JSX فقد لا تحتاج إلى استخدام المصانع إطلاقًا.
		</p>
	</li>
	<li>
		<p>
			يمكن إنشاء مصانع مخصصة إن كان ذلك ضروريًا.
		</p>
	</li>
</ul>
<h2>
	تعريف أحداث عقد React
</h2>

<p>
	يمكن إضافة الأحداث إلى عقد React كما لو أردنا إضافة الأحداث إلى عقد DOM. سنضيف في المثال الآتي حدثين بسيطين <code>click</code> و <code>mouseover</code> إلى عقدة <code>&lt;div&gt;</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_49" style="">
<span class="kwd">var</span><span class="pln"> mouseOverHandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> mouseOverHandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you moused over'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> clickhandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> clickhandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'you clicked'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
        </span><span class="str">'div'</span><span class="pun">,</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> onClick</span><span class="pun">:</span><span class="pln"> clickhandler</span><span class="pun">,</span><span class="pln"> onMouseOver</span><span class="pun">:</span><span class="pln"> mouseOverHandler </span><span class="pun">},</span><span class="pln">
        </span><span class="str">'click or mouse over'</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	لاحظ أنَّ اسم الخاصية لأحداث React تبدأ بالحرفين <code>'on'</code> وتُمرِّر في الكائن <code>props</code> المُمرَّر إلى الدالة <code>ReactElement()‎</code>.
</p>

<p>
	تُنشئ React ما تسميه <code>SyntheticEvent</code> لكل حدث، والذي يحتوي على تفاصيل الحدث، وهي شبيهة بتفاصيل الأحداث المُعرَّفة في DOM. يمكن مثلًا الاستفادة من نسخة الكائن <code>SyntheticEvent</code> بتمريره إلى معالجات الأحداث، وسأفعل ذلك في المثال الآتي لتسجيل تفاصيل الحدث <code>SyntheticEvent</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3822_51" style="">
<span class="kwd">var</span><span class="pln"> clickhandler </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> clickhandler</span><span class="pun">(</span><span class="typ">SyntheticEvent</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="typ">SyntheticEvent</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> reactNode </span><span class="pun">=</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
        </span><span class="str">'div'</span><span class="pun">,</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> onClick</span><span class="pun">:</span><span class="pln"> clickhandler</span><span class="pun">},</span><span class="pln">
        </span><span class="str">'click'</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="pln">reactNode</span><span class="pun">,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	كل كائن من النوع <code>syntheticEvent</code> يملك الخاصيات الآتية:
</p>

<ul>
<li>
		<p>
			bubbles
		</p>
	</li>
	<li>
		<p>
			cancelable
		</p>
	</li>
	<li>
		<p>
			DOMEventTarget currentTarget
		</p>
	</li>
	<li>
		<p>
			defaultPrevented
		</p>
	</li>
	<li>
		<p>
			eventPhase
		</p>
	</li>
	<li>
		<p>
			isTrusted
		</p>
	</li>
	<li>
		<p>
			DOMEvent nativeEvent
		</p>
	</li>
	<li>
		<p>
			void preventDefault()‎
		</p>
	</li>
	<li>
		<p>
			isDefaultPrevented()‎
		</p>
	</li>
	<li>
		<p>
			void stopPropagation()‎
		</p>
	</li>
	<li>
		<p>
			isPropagationStopped()‎
		</p>
	</li>
	<li>
		<p>
			DOMEventTarget target
		</p>
	</li>
	<li>
		<p>
			timeStamp
		</p>
	</li>
	<li>
		<p>
			type
		</p>
	</li>
</ul>
<p>
	هنالك خاصيات إضافية متوافرة اعتمادًا على نوع أو تصنيف الحدث المستخدم. فعلى سبيل المثال، الحدث <code>onClick</code> يحتوي على الخاصيات الآتية:
</p>

<ul>
<li>
		<p>
			altKey
		</p>
	</li>
	<li>
		<p>
			button
		</p>
	</li>
	<li>
		<p>
			buttons
		</p>
	</li>
	<li>
		<p>
			clientX
		</p>
	</li>
	<li>
		<p>
			clientY
		</p>
	</li>
	<li>
		<p>
			ctrlKey
		</p>
	</li>
	<li>
		<p>
			getModifierState(key‎)‎
		</p>
	</li>
	<li>
		<p>
			metaKey
		</p>
	</li>
	<li>
		<p>
			pageX
		</p>
	</li>
	<li>
		<p>
			pageY
		</p>
	</li>
	<li>
		<p>
			DOMEventTarget relatedTarget
		</p>
	</li>
	<li>
		<p>
			screenX
		</p>
	</li>
	<li>
		<p>
			screenY
		</p>
	</li>
	<li>
		<p>
			shiftKey
		</p>
	</li>
</ul>
<p>
	يحتوي الجدول الآتي على خصائص syntheticEvent المتاحة لكل تصنيف من تصنيفات الأحداث:
</p>

<table>
<thead><tr>
<th>
				نوع الحدث
			</th>
			<th>
				الأحداث
			</th>
			<th>
				خاصيات متعلقة به
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				الحافظة
			</td>
			<td>
				<ul>
<li>
						<code>onCopy</code>
					</li>
					<li>
						<code>onCut</code>
					</li>
					<li>
						<code>onPaste</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>DOMDataTransfer</code>
					</li>
					<li>
						<code>clipboardData</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				التركيب
			</td>
			<td>
				<ul>
<li>
						<code>onCompositionEnd</code>
					</li>
					<li>
						<code>onCompositionStart</code>
					</li>
					<li>
						<code>onCompositionUpdate</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>data</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				لوحة المفاتيح
			</td>
			<td>
				<ul>
<li>
						<code>onKeyDown</code>
					</li>
					<li>
						<code>onKeyPress</code>
					</li>
					<li>
						<code>onKeyUp</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>altKey</code>
					</li>
					<li>
						<code>charCode</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)‎</code>
					</li>
					<li>
						<code>key</code>
					</li>
					<li>
						<code>keyCode</code>
					</li>
					<li>
						<code>locale</code>
					</li>
					<li>
						<code>location</code>
					</li>
					<li>
						<code>metaKey</code>
					</li>
					<li>
						<code>repeat</code>
					</li>
					<li>
						<code>shiftKey</code>
					</li>
					<li>
						<code>which</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				التركيز
			</td>
			<td>
				<ul>
<li>
						<code>onChange</code>
					</li>
					<li>
						<code>onInput</code>
					</li>
					<li>
						<code>onSubmit</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>DOMEventTarget</code>
					</li>
					<li>
						<code>relatedTarget</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				النماذج
			</td>
			<td>
				<ul>
<li>
						<code>OnFocus</code>
					</li>
					<li>
						<code>onBlur</code>
					</li>
				</ul>
</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				الفأرة
			</td>
			<td>
				<ul>
<li>
						<code>onClick</code>
					</li>
					<li>
						<code>onContextMenu</code>
					</li>
					<li>
						<code>onDoubleClick</code>
					</li>
					<li>
						<code>onDrag</code>
					</li>
					<li>
						<code>onDragEnd</code>
					</li>
					<li>
						<code>onDragEnter</code>
					</li>
					<li>
						<code>onDragExit</code>
					</li>
					<li>
						<code>onDragLeave</code>
					</li>
					<li>
						<code>onDragOver</code>
					</li>
					<li>
						<code>onDragStart</code>
					</li>
					<li>
						<code>onDrop</code>
					</li>
					<li>
						<code>onMouseDown</code>
					</li>
					<li>
						<code>onMouseEnter</code>
					</li>
					<li>
						<code>onMouseLeave</code>
					</li>
					<li>
						<code>onMouseMove</code>
					</li>
					<li>
						<code>onMouseOut</code>
					</li>
					<li>
						<code>onMouseOver</code>
					</li>
					<li>
						<code>onMouseUp</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>altKey</code>
					</li>
					<li>
						<code>button</code>
					</li>
					<li>
						<code>buttons</code>
					</li>
					<li>
						<code>clientX</code>
					</li>
					<li>
						<code>clientY</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)‎</code>
					</li>
					<li>
						<code>metaKey</code>
					</li>
					<li>
						<code>pageX</code>
					</li>
					<li>
						<code>pageY</code>
					</li>
					<li>
						<code>DOMEventTarget</code>
					</li>
					<li>
						<code>relatedTarget</code>
					</li>
					<li>
						<code>screenX</code>
					</li>
					<li>
						<code>screenY</code>
					</li>
					<li>
						<code>shiftKey</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				الاختيار
			</td>
			<td>
				<ul>
<li>
						<code>onSelect</code>
					</li>
				</ul>
</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				اللمس
			</td>
			<td>
				<ul>
<li>
						<code>onTouchCancel</code>
					</li>
					<li>
						<code>onTouchEnd</code>
					</li>
					<li>
						<code>onTouchMove</code>
					</li>
					<li>
						<code>onTouchStart</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>AltKey</code>
					</li>
					<li>
						<code>DOMTouchList</code>
					</li>
					<li>
						<code>changedTouches</code>
					</li>
					<li>
						<code>ctrlKey</code>
					</li>
					<li>
						<code>getModifierState(key)‎</code>
					</li>
					<li>
						<code>metaKey</code>
					</li>
					<li>
						<code>shiftKey</code>
					</li>
					<li>
						<code>DOMTouchList</code>
					</li>
					<li>
						<code>targetTouches</code>
					</li>
					<li>
						<code>DOMTouchList</code>
					</li>
					<li>
						<code>touches</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				واجهة المستخدم
			</td>
			<td>
				<ul>
<li>
						<code>onScroll</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>detail</code>
					</li>
					<li>
						<code>DOMAbstractView</code>
					</li>
					<li>
						<code>view</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				الدولاب
			</td>
			<td>
				<ul>
<li>
						<code>onWheel</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>deltaMode</code>
					</li>
					<li>
						<code>deltaX</code>
					</li>
					<li>
						<code>deltaY</code>
					</li>
					<li>
						<code>deltaZ</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				الوسائط
			</td>
			<td>
				<ul>
<li>
						<code>onAbort</code>
					</li>
					<li>
						<code>onCanPlay</code>
					</li>
					<li>
						<code>onCanPlayThrough</code>
					</li>
					<li>
						<code>onDurationChange</code>
					</li>
					<li>
						<code>onEmptied</code>
					</li>
					<li>
						<code>onEncrypted</code>
					</li>
					<li>
						<code>onEnded</code>
					</li>
					<li>
						<code>onError</code>
					</li>
					<li>
						<code>onLoadedData</code>
					</li>
					<li>
						<code>onLoadedMetadata</code>
					</li>
					<li>
						<code>onLoadStart</code>
					</li>
					<li>
						<code>onPause</code>
					</li>
					<li>
						<code>onPlay</code>
					</li>
					<li>
						<code>onPlaying</code>
					</li>
					<li>
						<code>onProgress</code>
					</li>
					<li>
						<code>onRateChange</code>
					</li>
					<li>
						<code>onSeeked</code>
					</li>
					<li>
						<code>onSeeking</code>
					</li>
					<li>
						<code>onStalled</code>
					</li>
					<li>
						<code>onSuspend</code>
					</li>
					<li>
						<code>onTimeUpdate</code>
					</li>
					<li>
						<code>onVolumeChange</code>
					</li>
					<li>
						<code>onWaiting</code>
					</li>
				</ul>
</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				الصور
			</td>
			<td>
				<ul>
<li>
						<code>onLoad</code>
					</li>
					<li>
						<code>onError</code>
					</li>
				</ul>
</td>
			<td>
				 
			</td>
		</tr>
<tr>
<td>
				الحركات
			</td>
			<td>
				<ul>
<li>
						<code>onAnimationStart</code>
					</li>
					<li>
						<code>onAnimationEnd</code>
					</li>
					<li>
						<code>onAnimationIteration</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>animationName</code>
					</li>
					<li>
						<code>pseudoElement</code>
					</li>
					<li>
						<code>elapsedTime</code>
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				الانتقالات
			</td>
			<td>
				<ul>
<li>
						<code>onTransitionEnd</code>
					</li>
				</ul>
</td>
			<td>
				<ul>
<li>
						<code>propertyName</code>
					</li>
					<li>
						<code>pseudoElement</code>
					</li>
					<li>
						<code>elapsedTime</code>
					</li>
				</ul>
</td>
		</tr>
</tbody>
</table>
<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات.
		</p>
	</li>
	<li>
		<p>
			تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة <code>"Capture"</code> إلى اسم الحدث، أي أنَّ الحدث <code>onClick</code> سيصبح <code>onClickCapture</code>.
		</p>
	</li>
	<li>
		<p>
			إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية <code>nativeEvent</code> في كائن <code>SyntheticEvent</code> المُمرَّر إلى دالة معالجة الأحداث في React.
		</p>
	</li>
	<li>
		<p>
			لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation).
		</p>
	</li>
	<li>
		<p>
			يجب استخدام <code>e.stopPropagation()</code>‎ أو <code>e.preventDefault()</code>‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام <code>return false;</code>‎.
		</p>
	</li>
	<li>
		<p>
			لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام <a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">توابع دورة الحياة</a> في React.
		</p>
	</li>
</ul>
<p>
	ترجمة وبتصرف للفصل <a href="https://www.reactenlightenment.com/react-nodes.html" rel="external nofollow">React Nodes</a>‎ من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
]]></description><guid isPermaLink="false">776</guid><pubDate>Sat, 18 Jan 2020 13:07:00 +0000</pubDate></item><item><title>&#x62A;&#x647;&#x64A;&#x626;&#x629; React &#x648;&#x627;&#x644;&#x634;&#x631;&#x648;&#x639; &#x641;&#x64A; &#x627;&#x644;&#x639;&#x645;&#x644;</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-react-%D9%88%D8%A7%D9%84%D8%B4%D8%B1%D9%88%D8%B9-%D9%81%D9%8A-%D8%A7%D9%84%D8%B9%D9%85%D9%84-r775/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e163292d7d14___React_3.jpg.c61ba63f23a8571e61ca5ee4fb1cc6d5.jpg" /></p>

<p>
	سنتحدث في هذا المقال عن كيفية ضبط صفحة HTML لكي يمكن تفسيرها في متصفح الويب، وسيتمكن المتصفح في وقت التنفيذ من تحويل تعابير JSX ويشغِّل شيفرة React بنجاح.
</p>

<h2>
	استخدام react.js و react-dom.js في صفحة HTML
</h2>

<p>
	الملف <code>react.js</code> هو الملف الأساسي الذي نحتاج له لإنشاء عناصر React وكتابة مكونات React. عندما ترغب بعرض المكونات التي أنشأتها في مستند HTML (أي كتابتها إلى DOM) فستحتاج أيضًا إلى الملف <code>react-dom.js.</code> يعتمد الملف <code>react-dom.js</code> على الملف <code>react.js</code> ويجب تضمينه بعد تضمين الملف <code>react.js</code>.
</p>

<p>
	مثالٌ عن مستند HTML يحتوي على React:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5166_7" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react@16/umd/react.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	بتحميل الملفين <code>react.js</code> و <code>react-dom.js</code> في صفحة HTML، أصبح بإمكاننا إنشاء عقد ومكونات React ثم عرضها في DOM. المثال البسيط الآتي يُنشِئ مكوِّن <code>HelloMessage</code> يحتوي على عقدة العنصر <code>&lt;div&gt;</code> ثم سيُعرَض في شجرة DOM داخل عنصر HTML المُعرَّف <code>&lt;div id="app"&gt;&lt;/div&gt;</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5166_9" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
    </span><span class="tag">&lt;head&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react@16/umd/react.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/create-react-class@15.6.0-rc.0/create-react-class.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;script&gt;</span><span class="pln">
        </span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> createReactClass</span><span class="pun">({</span><span class="pln"> </span><span class="com">// استخدمنا هذه الوحدة لترى كيف تستعمل</span><span class="pln">
            displayName</span><span class="pun">:</span><span class="pln"> </span><span class="str">'HelloMessage'</span><span class="pun">,</span><span class="pln">
            render</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,</span><span class="kwd">null</span><span class="pun">,</span><span class="str">'Hello '</span><span class="pun">,</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
        </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">,{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Ahmed'</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	هذا كل ما تحتاج له لاستخدام React. لكنه لن يُمكِّنك من استخدام JSX، والتي سنناقشها في القسم التالي.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		لا تجعل العنصر <code>&lt;body&gt;</code> العنصر الأساسي في تطبيق React. احرص دومًا على وضع عنصر ؤ داخل <code>&lt;body&gt;</code>، وأعطه ID، ثم صيِّر (render) المكونات داخله. وهذا يعطي React مجالًا خاصًا بها لتجري التعديلات، دون أن تقلق عن أي شيءٍ آخر يجري تعديلات على العناصر الأبناء للعنصر <code>&lt;body&gt;</code>.
	</li>
</ul>
<h2>
	استخدام JSX عبر Babel
</h2>

<p>
	عملية إنشاء المكوِّن <code>HelloMessage</code> وعنصر <code>&lt;div&gt;</code> في المثال الآتي جرت باشتقاق الصنف <code>React.Component</code> واستخدام الدالة <code>React.createElement()</code>‎. يُفترَض أن تبدو الشيفرة الآتية مألوفةً لأنها مماثلة لشيفرة HTML من القسم السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5166_11" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react@16/umd/react.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;script&gt;</span><span class="pln">

      </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          render</span><span class="pun">(){</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hello '</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">

      </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Ahmed'</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">

  </span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكنك أن تستخدم JSX اختياريًا عبر Babel، فمن الممكن تبسيط عملية إنشاء عناصر React بتجريد استدعاءات الدالة <code>React.createElement()‎</code> ونكتبها بطريقة تشبه طريقة كتابة عناصر HTML.
</p>

<p>
	فبدلًا من كتابة الشيفرة الآتية التي تستخدم الدالة <code>React.createElement()</code>‎:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5166_13" style="">
<span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hello '</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span></pre>

<p>
	يمكننا أن نكتب ما يلي باستخدام JSX:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5166_15" style="">
<span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span></pre>

<p>
	ثم باستخدام Babel نستطيع تحويلها إلى الشيفرة التي تستخدم <code>React.createElement()‎</code> لكي يتمكن محرِّك JavaScript من تفسيرها.
</p>

<p>
	يمكننا القول مجازًا أنَّ JSX هي شكلٌ من أشكال HTML التي تستطيع كتابتها مباشرةً ضمن شيفرة JavaScript والتي تحتاج إلى خطوة إضافية هي التحويل، وتجرى عملية التحويل باستخدام Babel إلى شيفرة ECMAScript 5 لكي تتمكن المتصفحات من تشغيلها. بعبارةٍ أخرى، سيحوِّل Babel شيفرة JSX إلى استدعاءات للدالة <code>React.createElement()</code>‎.
</p>

<p>
	سنتحدث عن المزيد من تفاصيل JSX في القسم المخصص لها، لكننا الآن يمكننا أن نعدّ JSX على أنها طبقة تجريد اختيارية توفَّر للسهولة عند إنشاء عناصر React، ولن تعمل في متصفحات ES5 ما لم نحوِّلها بدايةً باستخدام Babel.
</p>

<h3>
	تحويل JSX عبر Babel في المتصفح
</h3>

<p>
	يُضبَط عادةً Babel لكي يُعالِج ملفات JavaScript أثناء عملية التطوير باستخدام أداة سطر الأوامر الخاصة به (عبر استخدام Webpack على سبيل المثال)؛ لكن من الممكن استخدام Babel مباشرةً في المتصفح بتضمين سكربت معيّن. ولمّا كنّا في بداياتنا فسنتفادى استخدام الأدوات التي تعمل من سطر الأوامر أو نتعلم استخدام مُحمِّل للوحدات، وذلك لكي ننطلق في React.
</p>

<h3>
	استخدام browser.js لتحويل JSX في المتصفح
</h3>

<p>
	حوّلنا مكوِّن React في مستند HTML الآتي إلى صياغة JSX، وستحدث عملية التحويل بسبب تضيمننا لملف <code>babel.min.js</code> وإعطائنا لعنصر <code>&lt;script&gt;</code> الخاصية <code>type</code> مع القيمة <code>text/``b``abel</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2057_8" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react@16/umd/react.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/@babel/standalone/babel.min.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/babel"</span><span class="tag">&gt;</span><span class="pln">

      </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// React.Component لاحظ استخدام </span><span class="pln">
          render</span><span class="pun">(){</span><span class="pln">
              </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">

      </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">HelloMessage</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Ahmed"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">

      </span><span class="com">/*** سابقًا ***/</span><span class="pln">
      </span><span class="com">/* var HelloMessage = createReactClass({
        *    render: function() {
        *        return &lt;div&gt;Hello {this.props.name}&lt;/div&gt;;
        *    }
        * });
        *
        * ReactDOM.render(&lt;HelloMessage name="Ahmed" /&gt;, document.getElementById('app'));
        */</span><span class="pln">
  </span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	تحويلنا لشيفرة JSX في المتصفح هو حلٌ سهلٌ وبسيط، لكنه ليس مثاليًا لأنَّ عملية التحويل تجري في وقت التشغيل، وبالتالي استخدام <code>babel.min.js</code> ليس حلًا عمليًا يمكن استخدامه في البيئات الإنتاجية.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			أداة Babel هي اختيار المطورين من فريق React لتحويل شيفرات ES*‎ وصيغة JSX إلى شيفرة ES5. تعلّم المزيد حول Babel بمراجعة <a href="https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md" rel="external nofollow">توثيقه</a>.
		</p>
	</li>
	<li>
		<p>
			باستخدام <a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">صيغة</a> <a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">JSX</a>:
		</p>

		<ul>
<li>
				<p>
					أصبح بإمكان الأشخاص غير المتخصصين تقنيًا فهم وتعديل الأجزاء المطلوبة. فيجد مطورو CSS والمصممون صيغة JSX أكثر ألفةً من شيفرة JavaScript.
				</p>
			</li>
			<li>
				<p>
					يمكنك استثمار كامل قدرات JavaScript في HTML وتتجنب تعلّم أو استخدام لغة خاصة بالقوالب. لكن اعلم أن JSX ليس محرّك قوالب، وإنما صيغة تصريحية للتعبير عن البنية الهيكلية الشجرية لمكونات UI.
				</p>
			</li>
			<li>
				<p>
					سيجد المُصرِّف (compiler) أخطاءً في شيفرة HTML الخاصة بك كنتَ ستغفل عنها.
				</p>
			</li>
			<li>
				<p>
					تحث صياغة JSX على فكر استخدام الأنماط السطرية (inline styles) وهو أمرٌ حسن.
				</p>
			</li>
		</ul>
</li>
	<li>
		<p>
			اعرف <a href="http://facebook.github.io/react/docs/jsx-gotchas.html" rel="external nofollow">محدوديات</a> JSX.
		</p>
	</li>
	<li>
		<p>
			تجري كتابة مواصفة JSX <a href="https://facebook.github.io/jsx/" rel="external nofollow">كمسودة</a> لكي تُستخدَم من أي شخص كإضافة لصياغة ECMAScript.
		</p>
	</li>
</ul>
<h2>
	استخدام ES6 و ES*‎ مع React
</h2>

<p>
	Babel ليس جزءًا من React، وليس الغرض من إنشاء Babel هو تحويل JSX، وإنما أُنشِئ كمُصرِّف JavaScript (‏compiler) بادئ الأمر. إذ يأخذ شيفرة ES<em>‎ ويحوِّلها لكي تعمل على المتصفحات التي لا تدعم شيفرة ES</em>‎. في هذه الآونة، يستخدم Babel أساسيًا لتحويل شيفرات ES6 و ES7 إلى ES5. عند إجراء عمليات التحويل هذه فمن البسيط تحويل تعابير JSX إلى استدعاءات <code>React.createElement()</code>‎.
</p>

<p>
	وبجانب تحويل Babel لشيفرات JSX، فيسمح أيضًا تحويل الشيفرات التي تعمل في إصدارات مستقبلية من ES*‎.
</p>

<p>
	مستند HTML الآتي يحتوي على مكوِّن <code>HelloMessage</code> مع إعادة كتابته لكي يستفيد من ميزة <a href="https://wiki.hsoub.com/JavaScript/class" rel="external">الأصناف</a> في ES6. فلن يحوِّل Babel صيغة JSX فحسب، بل سيحوِّل صيغة أصناف ES6 إلى صيغةٍ تستطيع المتصفحات التي تحتوي محرِّك ES5 تفسيرها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2057_10" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
    </span><span class="tag">&lt;head&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react@16/umd/react.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/react-dom@16/umd/react-dom.development.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
      </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://unpkg.com/@babel/standalone/babel.min.js"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"app"</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/babel"</span><span class="tag">&gt;</span><span class="pln">

        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// React.Component لاحظ استخدام </span><span class="pln">
            render</span><span class="pun">(){</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        </span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">HelloMessage</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"John"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span><span class="pln">

        </span><span class="com">/*** سابقًا ***/</span><span class="pln">
        </span><span class="com">/* var HelloMessage = createReactClass({
         *    render: function() {
         *        return &lt;div&gt;Hello {this.props.name}&lt;/div&gt;;
         *    }
         * });
         *
         * ReactDOM.render(&lt;HelloMessage name="John" /&gt;, document.getElementById('app'));
         */</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يأخذ Babel في المستند السابق الشيفرةَ الآتية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5166_21" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    render</span><span class="pun">(){</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">HelloMessage</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"John"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ويحولها إلى:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5166_23" style="">
<span class="str">"use strict"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> _createClass </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> defineProperties</span><span class="pun">(</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> props</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> props</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> descriptor </span><span class="pun">=</span><span class="pln"> props</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln"> descriptor</span><span class="pun">.</span><span class="pln">enumerable </span><span class="pun">=</span><span class="pln"> descriptor</span><span class="pun">.</span><span class="pln">enumerable </span><span class="pun">||</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln"> descriptor</span><span class="pun">.</span><span class="pln">configurable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="str">"value"</span><span class="pln"> in descriptor</span><span class="pun">)</span><span class="pln"> descriptor</span><span class="pun">.</span><span class="pln">writable </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">defineProperty</span><span class="pun">(</span><span class="pln">target</span><span class="pun">,</span><span class="pln"> descriptor</span><span class="pun">.</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> descriptor</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Constructor</span><span class="pun">,</span><span class="pln"> protoProps</span><span class="pun">,</span><span class="pln"> staticProps</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">protoProps</span><span class="pun">)</span><span class="pln"> defineProperties</span><span class="pun">(</span><span class="typ">Constructor</span><span class="pun">.</span><span class="pln">prototype</span><span class="pun">,</span><span class="pln"> protoProps</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">staticProps</span><span class="pun">)</span><span class="pln"> defineProperties</span><span class="pun">(</span><span class="typ">Constructor</span><span class="pun">,</span><span class="pln"> staticProps</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Constructor</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln"> </span><span class="pun">})();</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> _get </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">get</span><span class="pun">(</span><span class="pln">_x</span><span class="pun">,</span><span class="pln"> _x2</span><span class="pun">,</span><span class="pln"> _x3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> _again </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> _function</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">_again</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> object </span><span class="pun">=</span><span class="pln"> _x</span><span class="pun">,</span><span class="pln"> property </span><span class="pun">=</span><span class="pln"> _x2</span><span class="pun">,</span><span class="pln"> receiver </span><span class="pun">=</span><span class="pln"> _x3</span><span class="pun">;</span><span class="pln"> _again </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">object </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> object </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Function</span><span class="pun">.</span><span class="pln">prototype</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> desc </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">getOwnPropertyDescriptor</span><span class="pun">(</span><span class="pln">object</span><span class="pun">,</span><span class="pln"> property</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">desc </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> parent </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">getPrototypeOf</span><span class="pun">(</span><span class="pln">object</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">parent </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> _x </span><span class="pun">=</span><span class="pln"> parent</span><span class="pun">;</span><span class="pln"> _x2 </span><span class="pun">=</span><span class="pln"> property</span><span class="pun">;</span><span class="pln"> _x3 </span><span class="pun">=</span><span class="pln"> receiver</span><span class="pun">;</span><span class="pln"> _again </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> desc </span><span class="pun">=</span><span class="pln"> parent </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">continue</span><span class="pln"> _function</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="str">"value"</span><span class="pln"> in desc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> desc</span><span class="pun">.</span><span class="pln">value</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">var</span><span class="pln"> getter </span><span class="pun">=</span><span class="pln"> desc</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">getter </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">undefined</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> getter</span><span class="pun">.</span><span class="pln">call</span><span class="pun">(</span><span class="pln">receiver</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> _classCallCheck</span><span class="pun">(</span><span class="pln">instance</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Constructor</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!(</span><span class="pln">instance instanceof </span><span class="typ">Constructor</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TypeError</span><span class="pun">(</span><span class="str">"Cannot call a class as a function"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> _inherits</span><span class="pun">(</span><span class="pln">subClass</span><span class="pun">,</span><span class="pln"> superClass</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">typeof</span><span class="pln"> superClass </span><span class="pun">!==</span><span class="pln"> </span><span class="str">"function"</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> superClass </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TypeError</span><span class="pun">(</span><span class="str">"Super expression must either be null or a function, not "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pln"> superClass</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> subClass</span><span class="pun">.</span><span class="pln">prototype </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">create</span><span class="pun">(</span><span class="pln">superClass </span><span class="pun">&amp;&amp;</span><span class="pln"> superClass</span><span class="pun">.</span><span class="pln">prototype</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> constructor</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> subClass</span><span class="pun">,</span><span class="pln"> enumerable</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> writable</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> configurable</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">superClass</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">setPrototypeOf </span><span class="pun">?</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">.</span><span class="pln">setPrototypeOf</span><span class="pun">(</span><span class="pln">subClass</span><span class="pun">,</span><span class="pln"> superClass</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> subClass</span><span class="pun">.</span><span class="pln">__proto__ </span><span class="pun">=</span><span class="pln"> superClass</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">var</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">_React$Component</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    _inherits</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">,</span><span class="pln"> </span><span class="typ">_React$Component</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        _classCallCheck</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pun">);</span><span class="pln">

        _get</span><span class="pun">(</span><span class="typ">Object</span><span class="pun">.</span><span class="pln">getPrototypeOf</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">.</span><span class="pln">prototype</span><span class="pun">),</span><span class="pln"> </span><span class="str">"constructor"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">).</span><span class="pln">apply</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> arguments</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    _createClass</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[{</span><span class="pln">
        key</span><span class="pun">:</span><span class="pln"> </span><span class="str">"render"</span><span class="pun">,</span><span class="pln">
        value</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="pln">
                </span><span class="str">"div"</span><span class="pun">,</span><span class="pln">
                </span><span class="kwd">null</span><span class="pun">,</span><span class="pln">
                </span><span class="str">"Hello "</span><span class="pun">,</span><span class="pln">
                </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name
            </span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}]);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">HelloMessage</span><span class="pun">;</span><span class="pln">
</span><span class="pun">})(</span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pun">);</span><span class="pln">

</span><span class="pun">;</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">HelloMessage</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="str">"John"</span><span class="pln"> </span><span class="pun">}),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	أغلبية ميزات ES6 (مع بعض الاستثناءات الطفيفة) يمكن تحويلها باستخدام Babel.
</p>

<h3>
	ملاحظات
</h3>

<ul>
<li>
		<p>
			بالطبع ما يزال بإمكاننا استخدام Babel لغرضه الأساسي (وهو تصريف شيفرات JavaScript الحديثة إلى شيفرة JavaScript القديمة) دون استخدام JSX. لكن أغلبية المطورين الذين يستعملون Babel يستفيدون من قدرته على تحويل JSX إضافةً إلى ميزات ES*‎ غير المدعومة في المتصفحات القديمة.
		</p>
	</li>
	<li>
		<p>
			يمكنك مراجعة <a href="https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md" rel="external nofollow">توثيق</a> <a href="https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md" rel="external nofollow">Babel</a> لمزيدٍ من المعلومات.
		</p>
	</li>
</ul>
<h2>
	تجربة React في JSFiddle
</h2>

<p>
	يمكن استخدام نفس الضبط الذي أجريناه في هذا المقال مع JSFilddle. إذ تُستعمَل نفس الملفات (<code>react.js</code> و <code>react-dom.js</code> و <code>babel.min.js</code>) لجعل تنفيذ تطبيقات React سهلًا‎.‎
</p>

<p>
	<a href="https://jsfiddle.net/81br9kc7/" rel="external nofollow">هذا مثالٌ عن</a> JSFiddle يحتوي على مكوِّن HelloMessage المستخدم في هذا المقال.
</p>

<p>
	لاحظ أنَّ لسان Babel يشير إلى أنَّ شيفرة JavaScript الموجودة في هذا اللسان ستحوَّل باستخدام Babel. وإذا ضغطتَ على لسان Resources ستجد أنَّ JSFiddle يُضمِّن الملفين <code>react.js</code> و <code>react-dom.js</code>.
</p>

<p>
	سيُفتَرَض بعد قراءتك لهذا المقال أنَّك تدرك ما هي المتطلبات الأساسية لإعداد React و Babel عبر <code>babel.min.js</code>، وصحيحٌ أنَّ JSFiddle لا يُصرِّح بوضوح عن طريقة إعداده، لكنه يستخدم نفس الضبط السابق (أو ما يشبهه) لتشغيل شيفرات React.
</p>

<p>
	ترجمة وبتصرف للفصل <a href="https://www.reactenlightenment.com/react-basic-setup.html" rel="external nofollow">React Setup</a>‎ من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
]]></description><guid isPermaLink="false">775</guid><pubDate>Wed, 15 Jan 2020 13:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x635;&#x637;&#x644;&#x62D;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x62E;&#x62F;&#x645;&#x629; &#x641;&#x64A; React</title><link>https://academy.hsoub.com/programming/javascript/react/%D8%A7%D9%84%D9%85%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-react-r774/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e16303ac8f96___React_2.jpg.ddf748c681ae9ff80c63a16abec724ee.jpg" /></p>

<p>
	قبل أن نتعرف سويةً على آلية عمل React، دعنا نتعرف بدايةً على بعض المصطلحات التي ستسهِّل عملية التعليم. سأورد قائمةً من المصطلحات الشائعة، إضافةً إلى تعريفاتها، وسنستعمل هذه المصطلحات أثناء حديثنا عن React.
</p>

<h2>
	Babel
</h2>

<p>
	يحوِّل <a href="https://babeljs.io/" rel="external nofollow">Babel</a> شيفرة JavaScript ES<em>‎ (أي JS 2015 و JS 2016 و JS 2017) إلى شيفرة ES5. إنَّ Babel هي أداة من اختيار مطوري React لكتابة شيفرات ES</em>‎ وتحويل JSX إلى شيفرة ES5.
</p>

<h2>
	Babel CLI
</h2>

<p>
	يأتي Babel مع أداة تعمل من سطر الأوامر تسمى <a href="https://babeljs.io/docs/usage/cli/" rel="external nofollow">Babel CLI</a>، ويمكن أن تستخدم لبناء الملفات من سطر الأوامر.
</p>

<h2>
	خيارات ضبط المكونات (Component Configuration Options)
</h2>

<p>
	وهي وسائط الضبط التي تُمرَّر (ككائن) إلى الدالة <code>React.createClass()</code>‎ أو الدالة البانية (في حال كنت تستعمل الأصناف في ES6) مما ينتج نسخةً (instance) من مكوِّن React.
</p>

<h2>
	توابع دورة حياة المكونات (Component Life Cycle Methods)
</h2>

<p>
	<a href="https://wiki.hsoub.com/React/state_and_lifecycle" rel="external">توابع دورة حياة المكونات</a> هي مجموعة فرعية من أحداث المكونات، المفصولة (اصطلاحيًا) عن الخيارات الأخرى لضبط المكونات، أي هي:
</p>

<ul>
<li>
		<code>componentWillUnmount</code>
	</li>
	<li>
		<code>componentDidUpdate</code>
	</li>
	<li>
		<code>UNSAFE_componentWillUpdate</code>
	</li>
	<li>
		<code>shouldComponentUpdate</code>
	</li>
	<li>
		<code>UNSAFE_componentWillReceiveProps</code>
	</li>
	<li>
		<code>componentDidMount</code>
	</li>
	<li>
		<code>UNSAFE_componentWillMount</code>
	</li>
</ul>
<p>
	تُنفَّذ هذه التوابع في نقاط مُحدَّدة من دورة حياة المكوِّن.
</p>

<h2>
	شجرة DOM‏ (Document Object Model)
</h2>

<p>
	شجرة DOM هي الواجهة البرمجية لمستندات HTML و XML و SVG، وهي توفِّر تمثيلًا هيكليًا للمستند كشجرة. تُعرِّف DOM الدوال التي تسمح بالوصول إلى الشجرة، لذا يمكنها تغيير بنية المستند وأنماط التنسيق التابعة له ومحتواه.
</p>

<p>
	توفِّر DOM تمثيلًا للمستند على شكل مجموعة مهيكلة من العقد (nodes) والكائنات (objects)، والتي تملك مختلف الخاصيات (properties) والتوابع (methods). يمكن أن تملك العقد معالجات أحداث (event handlers) مرتبطة بها، وستستدعى تلك المعالجات عند تفعيل الحدث. باختصار، تصل شجرة DOM بين صفحات الويب ولغات البرمجة.
</p>

<h2>
	ES5
</h2>

<p>
	الإصدار الخامس من معيار ECMAScript.
</p>

<h2>
	ES6 أو ECMAScript 2015
</h2>

<p>
	الإصدار السادس من معيار ECMAScript، والذي يحتوي على إضافات كثيرة على لغة JavaScript.
</p>

<h2>
	ES7 أو ECMAScript 2016
</h2>

<p>
	الإصدار السابع من معيار ECMAScript.
</p>

<h2>
	ES*‎
</h2>

<p>
	تستخدم لتمثيل النسخة الحالية من JavaScript إضافةً إلى الإصدارات المستقبلية، والتي يمكن الكتابة بها باستخدام أدوات مثل Babel.
</p>

<p>
	عندما ترى «ES*‎» فمن المرجح أنَّ المقصود بها هو ES5 و ES6 و ES7 معًا.
</p>

<h2>
	JSX
</h2>

<p>
	<a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">JSX</a> هي صيغة إضافية اختيارية تشبه XML لمعيار ECMAScript التي يمكن أن تُستخدم لتعريف بنية شجريّة شبيهة بلغة HTML في ملفات JavaScript. ستحوَّل تعابير JSX في ملف JavaScript إلى صياغة JavaScript قبل أن يتمكن محرِّك JavaScript من تفسير الملف. تُستَخدم برمجية Babel عادةً لتحويل تعابير JSX.
</p>

<h2>
	Node.js
</h2>

<p>
	<a href="https://wiki.hsoub.com/Node.js" rel="external">Node.js</a> هي بيئة تشغيل مفتوحة المصدر ومتعددة المنصات لكتابة شيفرات JavaScript. بيئة التشغيل Node.js تُفسِّر شيفرات JavaScript باستخدام محرِّك V8.
</p>

<h2>
	npm
</h2>

<p>
	<a href="https://www.npmjs.com/" rel="external nofollow">npm</a> هو مدير حزم للغة JavaScript نَشَأ من مجتمع Node.js.
</p>

<h2>
	خاصيات React (أي React props<code>)</code>
</h2>

<p>
	يمكنك أن تعدّ الخاصيات (<code>props</code>) على أنها خيارات الضبط لعقد React، وفي نفس الوقت يمكنك أن تتخيلها كخاصيات HTML.
</p>

<p>
	تملك الخاصيات عدِّة أدوار:
</p>

<ol>
<li>
		<p>
			يمكن أن تصبح خاصيات HTML، فلو طابقت خاصيةٌ ما إحدى خاصيات HTML فستُضاف كخاصية HTML في شجرة DOM النهائية.
		</p>
	</li>
	<li>
		<p>
			الخاصيات المُمرَّرة إلى الدالة <code>createElement()‎</code> تصبح قيمًا مخزنةً في الكائن <code>prop</code> كنسخة (instance) من <code>React.createElement()</code>‎ أي <code>‎[INSTANCE].props.[NAME_OF_PROP]‎</code> تستخدم الخاصيات بكثرة لتمرير قيم إلى المكونات.
		</p>
	</li>
	<li>
		<p>
			بعض الخاصيات لها تأثيرات جانبية (مثل <code>key</code> و <code><a href="https://wiki.hsoub.com/React/refs_and_the_dom" rel="external">ref</a></code> و <code><a href="https://wiki.hsoub.com/React/dom_elements#dangerouslySetInnerHTML" rel="external">dangerouslySetInnerHTML</a>)</code>.
		</p>
	</li>
</ol>
<h2>
	React
</h2>

<p>
	<a href="https://wiki.hsoub.com/React" rel="external">React</a> هي مكتبة JavaScript تُستخدم لكتابة واجهات للمستخدمة بمرونة وكفاءة وفعالية عالية.
</p>

<h2>
	مكوِّن React
</h2>

<p>
	يُنشَأ مكوِّن React باستدعاء الوحدة <code>create-react-class</code> (أو <code>React.Component</code> عند استخدام الأصناف في ES6). هذه الدالة تأخذ كائنًا من الخيارات الذي يُستخدَم لضبط وإنشاء مكونات React. أحد أشهر خيارات الضبط هو الدالة <code>render</code> التي تعيد عقد React أي React nodes. والتالي يمكننك أن تعدّ مكوِّن React على أنه تجريد (abstraction) يحتوي على مكوِّن أو عقدة React واحد أو أكثر.
</p>

<h2>
	الوحدة create-react-class
</h2>

<p>
	توفر هذه <a href="https://www.npmjs.com/package/create-react-class" rel="external nofollow">الوحدة</a> طريقة لإنشاء مكونات React دون إنشاء صنف جديد وجعله مشتقًا من الصنف <code>React.Component</code>. هذه الوحدة موجودة لكتابة <a href="https://wiki.hsoub.com/React/react_without_es6" rel="external">شيفرات</a> <a href="https://wiki.hsoub.com/React/react_without_es6" rel="external">React.js</a> دون ES6.
</p>

<h2>
	عقد عناصر React
</h2>

<p>
	عقد عناصر React (‏React Element Nodes أو ReactElement) هو تمثيل يشبه عناصر HTML في شجرة DOM يُنشَأ باستخدام <code>React.createElement()‎;‎</code>.
</p>

<h2>
	عقد React
</h2>

<p>
	عقد React (‏React Nodes أي عقد العناصر والعقد النصية) هو نوع الكائنات الرئيسي في React ويمكن إنشاؤه باستخدام <code>React.createElement('div');‎</code>. بعبارةٍ أخرى، عقد React هي كائنات تُمثِّل عقد DOM وعقد DOM الأبناء التابعة لها. وهي تمثيلٌ خفيفٌ وعديم الحالة (stateless) وغير قابلٍ للتعديل (immutable) لعقدة DOM.
</p>

<h2>
	مصانع عقد React
</h2>

<p>
	<a href="https://reactjs.org/warnings/legacy-factories.html" rel="external nofollow">مصانع عقد</a> React (‏React Node Factories) هي دالة تولِّد عقد عنصر React ذات نوعٍ (type) مُحدَّد. كانت هذه الخاصية موجودة في إصدارات سابقة من React.js ثم أهملت.
</p>

<h2>
	دالة مكون React عديم الحالة
</h2>

<p>
	أي React Stateless Function Component، وتكون عندما يتألف المكوِّن من الخاصيات فقط، دون حالة، ويمكن أن يكتب المكوِّن كدالة نقية مما يجعلنا نتجنب إنشاء نسخة من مكوِّن React.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7278_9" style="">
<span class="kwd">var</span><span class="pln"> </span><span class="typ">MyComponent</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">props</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{</span><span class="pln">props</span><span class="pun">.</span><span class="pln">name</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MyComponent</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"Ahmed"</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> app</span><span class="pun">);</span></pre>

<h2>
	عقد عناصر React
</h2>

<p>
	عقد عناصر React (‏React Text Nodes، أي ReactText) هي تمثيل للعقد النصية في شجرة DOM الوهمية كما في <code>React.createElement('div', null, 'a text node');</code>‎.
</p>

<h2>
	شجرة DOM الوهمية (Virtual DOM)
</h2>

<p>
	Virtual DOM هي شجرة مخزَّنة في ذاكرة JavaScript لعناصر ومكونات React وتُستخدَم لإعادة تصيير (re-render) شجرة DOM بكفاءة عالية (بمعرفة الاختلافات بينها وبين شجرة DOM الحقيقية).
</p>

<h2>
	Webpack
</h2>

<p>
	<a href="https://webpack.github.io/" rel="external nofollow">Webpack</a> هو مُحمِّل للوحدات (modules) والمجمِّع (bundler) لها، والذي يأخذ الوحدات (‎<code>.js</code> أو <code>‎.css</code> أو <code>‎.txt</code> …إلخ.) مع اعتمادياتها ويولِّد وسائط ساكنة (static assets) تُمثِّل هذه الوحدات.
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://www.reactenlightenment.com/react-semantics.html" rel="external nofollow">React Semantics</a>‎ من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
]]></description><guid isPermaLink="false">774</guid><pubDate>Sat, 11 Jan 2020 13:04:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x647;&#x64A; React&#x61F;</title><link>https://academy.hsoub.com/programming/javascript/react/%D9%85%D8%A7-%D9%87%D9%8A-react%D8%9F-r773/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_01/5e1627b535a72___React_1.jpg.83209f8e42c50e38a7ef90a0d158bd80.jpg" /></p>

<p>
	React.js هي مكتبة JavaScript التي يمكن أن تستخدم لبناء واجهات المستخدم؛ فباستخدام React يمكن للمستخدمين إنشاء مكوِّنات قابلة لإعادة الاستخدام، وهذه المكونات تظهر البيانات أثناء تغيِّرها مع الزمن. يسمح لنا React Native بإنشاء تطبيقات أصيلة للهواتف الذكية باستخدام React. بكلمات أخرى، React هي أداة في JavaScript التي تُسهِّل إنشاء وصيانة واجهات المستخدم ذات الحالة (stateful) وعديمة الحالة (stateless)، وتوفر القدرة على تعريف وتقسيم واجهة المستخدم إلى مكوِّنات منفصلة (تسمى أيضًا بمكونات React) باستخدام عقد شبيهة بلغة HTML تسمى عقد React (أي React nodes). ستتحول عقد React في النهاية إلى صيغة قابلة للعرض في واجهات المستخدم (مثل HTML/DOM أو canvas أو SVG …إلخ.).
</p>

<p>
	يمكنني أن أستفيض بالشرح محاولًا تعريف React باستخدام الكلمات، لكنني أظن أنَّ من الأفضل أن أريك ما تفعله. لا تحاول أن تفهم كل التفاصيل الدقيقة أثناء شرحي لما بقي من هذا المقال، فالغرض من بقية <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20react/" rel="">هذه السلسلة</a> أن تشرح لك بالتفصيل ما سيرد في هذه المقدمة.
</p>

<h2>
	استخدام React لإنشاء مكونات شبيهة بعنصر ‎select&gt;‎&gt;
</h2>

<p>
	ما يلي هو عنصر <code><a href="https://wiki.hsoub.com/HTML/select" rel="external">&lt;select&gt;</a></code> يحتوي على عناصر <code><a href="https://wiki.hsoub.com/HTML/option" rel="external">&lt;option&gt;</a></code>. لحسن الحظ، الغرض من العنصر <code>&lt;select&gt;</code> معروفٌ لديك:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9727_8" style="">
<span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">size</span><span class="pun">=</span><span class="atv">"4"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">Volvo</span><span class="tag">&lt;/option&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">Saab</span><span class="tag">&lt;/option&gt;</span><span class="pln">
  </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">selected</span><span class="tag">&gt;</span><span class="pln">Mercedes</span><span class="tag">&lt;/option&gt;</span><span class="pln">
  </span><span class="tag">&lt;option&gt;</span><span class="pln">Audi</span><span class="tag">&lt;/option&gt;</span><span class="pln">
</span><span class="tag">&lt;/select&gt;</span></pre>

<p>
	عندما يفسِّر المتصفح الشجرة السابقة من العناصر فسيُنتِج واجهة مستخدم تحتوي على قائمة نصية من العناصر التي يمكن اختيارها.
</p>

<p>
	أما في المتصفح، فشجرة DOM وشجرة <a href="https://wiki.hsoub.com/React/faq_internals#.D9.87.D9.84_DOM_.D8.A7.D9.84.D8.AE.D9.8A.D8.A7.D9.84.D9.8A_.28Shadow_DOM.29_.D9.87.D9.88_.D9.86.D9.81.D8.B3.D9.87_DOM_.D8.A7.D9.84.D8.A7.D9.81.D8.AA.D8.B1.D8.A7.D8.B6.D9.8A_.28Virtual_DOM.29.D8.9F" rel="external">DOM</a> الظل (shadow DOM) تعملان معًا خلف الكواليس لتحويل العنصر <code>&lt;select&gt;</code> إلى مكوِّن UI. لاحظ أنَّ المكوِّن <code>&lt;select&gt;</code> يسمح للمستخدم باختيار أحد العناصر وبالتالي سيُخزِّن حالة ذاك الاختيار (أي انقر على Volvo وستختارها بدلًا من Mercedes).
</p>

<p>
	يمكننا باستخدام React إنشاء مكوِّن <code>&lt;select&gt;</code> خاص بنا باستخدام عقد React لإنشاء مكوِّن React والذي في النهاية سيُنتِج عناصر HTML في شجرة DOM.
</p>

<p>
	لنُنشِئ مكوِّنًا خاصًا بنا شبيهًا بالعنصر <code>&lt;select&gt;</code> باستخدام React.
</p>

<h2>
	تعريف مكون React (أي React Component)
</h2>

<p>
	سنُنشِئ فيما يلي مكوِّن React باشتقاق الصنف (<a href="https://wiki.hsoub.com/JavaScript/class" rel="external">class</a>‎) ‏<code>React.Component</code> لإنشاء المكوِّن <code>MySelect</code>.
</p>

<p>
	كما ترى، المكوِّن <code>MySelect</code> مُنشَأ من عدِّة أنماط إضافةً إلى عقدة <code><a href="https://wiki.hsoub.com/HTML/div" rel="external">&lt;div&gt;</a></code> فارغة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6976_7" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// MySelect تعريف المكوِّن </span><span class="pln">
  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
      </span><span class="com">// JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل </span><span class="pln">
      </span><span class="com">// JSX باستخدام &lt;div&gt; سنعيد عنصر</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln"> 
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	العنصر <code>&lt;div&gt;</code> السابق شبيهٌ بعناصر HTML العادية، وهو موجودٌ داخل شيفرة JavaScript التي تسمى JSX! <a href="https://wiki.hsoub.com/React/introducing_jsx" rel="external">صيغة</a> JSX هي صياغة JavaScript اختيارية ومخصصة التي تستخدمها مكتبة React للتعبير عن عقد React التي يمكن أن ترتبط مع عناصر HTML حقيقية، أو عناصر مخصصة، أو عقد نصية. علينا ألّا نفترض أنَّ عقد React المُعرَّفة باستخدام JSX مماثلة تمامًا لعناصر HTML، فهنالك بعض الاختلافات بينها، وبعض القصور أيضًا.
</p>

<p>
	يجب تحويل صياغة JSX إلى شيفرات JavaScript حقيقية التي يمكن تفسيرها من محركات ECMAScript 5، فإن لم تحوّل الشيفرة السابقة فستسبب خطأً في JavaScript.
</p>

<p>
	الأداة الرسمية لتحويل شيفرات JSX إلى شيفرات JavaScript تسمى <a href="http://babeljs.io/" rel="external nofollow">Babel</a>. بعد أن يحوِّل Babel العنصر <code>&lt;div&gt;</code> في الشيفرة السابقة إلى شيفرة JavaScript فستبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9727_13" style="">
<span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">'div'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> style</span><span class="pun">:</span><span class="pln"> mySelectStyle </span><span class="pun">});</span></pre>

<p>
	بدلًا من:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9727_15" style="">
<span class="pln">return </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}</span><span class="tag">&gt;&lt;/div&gt;</span><span class="pln">;</span></pre>

<p>
	في الوقت الحالي، ضع في ذهنك أنَّه عندما تكتب عناصر شبيهة بعناصر HTML في شيفرة React فستحوَّل في نهاية المطاف إلى شيفرة JavaScript حقيقية، إضافةً إلى تحويل أي شيفرة مكتوبة تحتوي على ميزات ECMAScript 6 وما بعدها إلى ECMAScript 5.
</p>

<p>
	المكوِّن <code>&lt;MySelect&gt;</code> يحتوي -عند هذه النقطة- على عقدة <code>&lt;div&gt;</code> فارغة فقط، أي أنَّ مكوِّن دون أي فائدة، لذا دعونا نغيِّر ذلك.
</p>

<p>
	سنُعرِّف مكونًا آخر باسم <code>&lt;MyOption&gt;</code> وسنستخدم المكوِّن <code>&lt;MyOption&gt;</code> داخل المكوِّن <code>&lt;MySelect&gt;</code> (ويسمى ذلك <a href="https://wiki.hsoub.com/React/composition_vs_inheritance" rel="external">التركيب</a> أي composition).
</p>

<p>
	تفحَّص شيفرة JavaScript المُحدَّثة الآتية التي تُعرِّف كلًا من مكونَي <code>&lt;MySelect&gt;</code> و <code>&lt;MyOption&gt;</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6976_9" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// MySelect تعريف المكوِّن </span><span class="pln">
  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل</span><span class="pln">
    </span><span class="com">// &lt;MyOption&gt; يحتوي على المكون JSX باستخدام &lt;div&gt; إعادة عنصر</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> 
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// MyOption تعريف المكون </span><span class="pln">
    render</span><span class="pun">(){</span><span class="pln">
      </span><span class="com">// JSX باستخدام &lt;div&gt; إعادة عنصر</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">    
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يفترض أنَّك لاحظت وجود المكوِّن <code>&lt;MyOption&gt;</code> داخل المكوِّن <code>&lt;MySelect&gt;</code> والذين أنشأناهما باستخدام JSX.
</p>

<h2>
	تمرير خيارات المكون باستخدام خاصيات React
</h2>

<p>
	لاحظ أنَّ المكوِّن <code>&lt;MyOption&gt;</code> يتألف من عنصر <code>&lt;div&gt;</code> يحتوي على التعبير <code>{this.props.value}</code>. تُستخدَم الأقواس المعقوفة <code>{}</code> داخل JSX للإشارة أنَّ محتواها هو تعبيرٌ صالحٌ في JavaScript. بعبارة أخرى، يمكننا أن نكتب شيفرات JavaScript عادية داخل القوسين <code>{}</code>.
</p>

<p>
	استخدمنا القوسين <code>{}</code> للوصول إلى الخاصيات المُمرَّرة إلى المكوِّن <code>&lt;MyOption&gt;</code>. بعبارةٍ أخرى، عندما يعرض المكوِّن <code>&lt;MyOption&gt;</code> فستوضع قيمة الخيار <code>value</code> التي جرى تمريرها عبر خاصيةٍ شبيهةٍ بخاصيات HTML (أي <code>value="Volvo"</code>‎) داخل عنصر <code>&lt;div&gt;</code>. هذه الخاصيات التي تشبه خاصيات HTML تسمى خاصيات React، وتستخدمها مكتبة React لتمرير الخيارات التي لا تتغير إلى المكوِّنات، ومرَّرنا في مثالنا الخاصية <code>value</code> إلى المكوِّن <code>&lt;MyOption&gt;</code>، والأمر لا يختلف عن تمرير وسيط إلى <a href="https://wiki.hsoub.com/JavaScript/Functions" rel="external">دالة</a> <a href="https://wiki.hsoub.com/JavaScript/Functions" rel="external">JavaScript</a>، وهذا ما تفعله JSX خلف الكواليس.
</p>

<h2>
	تصيير (Render) مكوِّن إلى شجرة DOM الافتراضية (Virtual DOM) ثم إلى شجرة DOM
</h2>

<p>
	في هذه المرحلة، عرَّفنا مكوِّنين من مكونات React، لكننا لم نصيِّرها إلى شجرة DOM الافتراضية ومنها إلى شجرة HTML DOM.
</p>

<p>
	قبل أن نفعل ذلك، أود أن أشير إلى أنَّ كل ما فعلناه هو تعريف مكونين باستخدام JavaScript. وكل ما فعلناه -نظريًا- هو تعريف مكونات UI، وليس من الضروري أن تذهب هذه المكونات إلى شجرة DOM أو حتى إلى شجرة DOM الافتراضية (Virtual DOM). ويمكننا -نظريًا- أن نصيّر (render) هذه المكونات إلى منصة من منصات الهواتف الذكية أو إلى العنصر <code><a href="https://wiki.hsoub.com/HTML/canvas" rel="external">&lt;canvas&gt;</a>)</code>، لكننا لن نفعل ذلك هنا. تذكّر أنَّ استخدام React يمنحنا تنظيمًا لعناصر واجهة المستخدم التي يمكن تحويلها إلى شجرة DOM أو تطبيقاتٍ أخرى.
</p>

<p>
	لنصيّر الآن المكوِّن <code>&lt;MySelect&gt;</code> إلى شجرة DOM الافتراضية والتي بدورها ستصيّر إلى شجرة DOM الأساسية داخل صفحة HTML.
</p>

<p>
	في شيفرة JavaScript التالية، ستلاحظ أننا أضفنا استدعاءً للدالة <code><a href="https://wiki.hsoub.com/React/react_dom#render.28.29.E2.80.8E" rel="external">ReactDOM.render()</a></code>‎ في آخر سطر، ومررنا إلى الدالة <code><a href="https://wiki.hsoub.com/React/react_dom#render.28.29.E2.80.8E" rel="external">ReactDOM.render()‎</a></code> المكوِّن الذي نريد تصييره (وهو <code>&lt;MySelect&gt;</code>) ومرجعية إلى عنصر HTML موجودٌ في شجرة HTML DOM (وهو <code>&lt;div id="app"&gt;&lt;/div&gt;</code>) الذي نريد عرض المكوِّن <code>&lt;MySelect&gt;</code> فيه.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6976_11" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// MySelect تعريف المكوِّن </span><span class="pln">
  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل </span><span class="pln">
    </span><span class="com">// &lt;MyOption&gt; يحتوي على المكون JSX باستخدام &lt;div&gt; إعادة عنصر</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> 
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="com">// MyOption تعريف المكون </span><span class="pln">
    render</span><span class="pun">(){</span><span class="pln">
      </span><span class="com">// JSX باستخدام &lt;div&gt; إعادة عنصر</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln"> 
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MySelect</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	لاحظ أنَّ كل ما فعلناه هو إخبار React أين ستبدأ بتصيير المكونات وما هي المكونات التي عليها بدء التصيير بها. بعد ذلك ستصيّر React أيّة مكونات محتواة داخل المكوِّن الأصلي (مثل المكوِّن <code>&lt;MyOption&gt;</code> داخل <code>&lt;MySelect&gt;</code>).
</p>

<p>
	انتظر لحظة! ربما تفكِّر الآن أننا لم نُنشِئ العنصر <code>&lt;select&gt;</code> أصلًا، وكل ما فعلناه هو إنشاء قائمة ثابتة عديم الحالة من السلاسل النصية. سنصلح ذلك في الخطوة القادمة.
</p>

<p>
	قبل أن نكمل إلى الخطوة القادمة، أحب أن أشير إلى عدم وجود أي تعاملات ضمنية مع شجرة DOM لكي نعرض المكوِّن <myselect> في شجرة DOM. بعبارةٍ أخرى، لم نستدعِ شيفرة jQuery أثناء إنشاء هذا المكوِّن؛ وجميع التعاملات مع شجرة DOM الفعلية قد أصبحت مجردةً (abstract) عبر استعمال شجرة DOM الافتراضية الخاصة بمكتبة React. في الواقع، عندما نستخدم React فما نفعله هو وصف شجرة DOM الافتراضية التي تأخذها React وتحوِّلها إلى شجرة DOM الفعلية لنا.</myselect></p>

<h2>
	استخدام حالة React (أي React state)
</h2>

<p>
	لكي نجعل عنصر <code>&lt;MySelect&gt;</code> الخاص بنا يحاكي عنصر <code>&lt;select&gt;</code> الأصلي في HTML فعلينا أن نضيف حالةً (state) له. فما فائدة عنصر <code>&lt;select&gt;</code> المخطط إذا لم يكن قادرًا على الاحتفاظ بقيمة الاختيار الذي اخترناه.
</p>

<p>
	تأتي الحالة (state) عندما يحتوي المكوِّن على نسخة من المعلومات. وبخصوص عنصر <code>&lt;MyOption&gt;</code> المخصص، الحالة هي النص المختار حاليًا أو عدم وجود نص مختار من الأساس. لاحظ أنَّ الحالة تتضمن عادةً أحداثًا تابعة للمستخدم (مثل الفأرة أو لوحة المفاتيح أو حافظة النسخ …إلخ.) أو أحداثًا تابعة للشبكة (أي AJAX) وتستخدم قيمتها لتحديد إن كانت واجهة المستخدم للمكوِّن تحتاج إلى إعادة تصيير (re-render، فتغيير القيمة سيؤدي إلى إعادة التصيير).
</p>

<p>
	ترتبط الحالة عادةً بأعلى مكوِّن الذي يُنشِئ مكوِّن UI. كنا في السابق نستخدم الدالة <code>getInitialState()</code>‎ في React لنستطيع ضبط الحالة الافتراضية، فلو أردنا ضبط حالة المكون إلى false (أي لا يوجد أي نص مختار) فسنعيد كائن حالة عند استدعاء الدالة <code>getInitialState()</code>‎ (أي <code>return {selected: false};</code>‎). دورة حياة الدالة <code>getInitialState()‎</code> هي استدعاء الدالة مرةً قبل تركيب المكوِّن، وستُستخدَم القيمة المعادة منها كقيمة افتراضية للخاصية <code>this.state</code>.
</p>

<p>
	الطريقة السابقة قديمة ولم تعد مستخدمةً إلا إذا كنتَ من محبي الوحدة <code>create-react-class</code> والتي سنأتي على ذكرها لاحقًا، أما في الأصناف في ES6، فنحن نستعمل <code>this.state</code> ضمن الدالة البانية (constructor) للصنف الخاص بالمكون. أي أننا سنكتب في الدالة البانية للصنف <code>MySelect</code> تعريفًا للحالة التي نريدها.
</p>

<p>
	هذه نسخة مُحدَّثة من الشيفرة أضفنا فيها الحالة إلى المكوِّن، أنصحك بقراءة التعليقات التي أضعها في الشيفرة والتي تجذب انتباهك إلى التغييرات التي حدثت في الشيفرة.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9727_24" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  constructor</span><span class="pun">(){</span><span class="pln"> </span><span class="com">// إضافة الحالة الافتراضية</span><span class="pln">
    super</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">};</span><span class="pln"> </span><span class="com">// this.state.selected = false;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MySelect</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	بعد ضبط الحالة الافتراضية، سنستدعي دالة رد نداء (callback function) باسم <code>select</code> التي ستُطلَق عندما يضغط المستخدم على خيارٍ ما. داخل هذه الدالة سنحصل على نص الخيار الذي اختاره المستخدم (عبر المعامل <code>event</code>) وسنستخدمه لضبط الحالة <code>setState</code> للمكوِّن الحالي. لاحظ أننا نستخدم تفاصيل الكائن <code>event</code> المُمرَّر إلى دالة رد النداء <code>select</code>. يُفترَض أنَّ هذا النمط من البرمجة مألوفٌ لديك إن كانت لديك أيّ خبرة مع مكتبة <a href="https://wiki.hsoub.com/jQuery" rel="external">jQuery</a> من قبل.
</p>

<p>
	من أهم ما يجب ملاحظته في الشيفرة الآتية هو اتباع التوابع في مكوّنات React المُعرَّفة كأصناف ES6 لنفس القواعد في أصناف ES6 الاعتيادية، يعني هذا أنّها لا تربط <code>this</code> بنسخة الكائن، بل يجب عليك أن تستخدم بشكل صريح التابع ‎<code><a href="https://wiki.hsoub.com/JavaScript/Function/bind" rel="external">.bind(this)</a></code>‎ في الدالة البانية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6976_14" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  constructor</span><span class="pun">(){</span><span class="pln"> </span><span class="com">// إضافة الحالة الافتراضية</span><span class="pln">
    super</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">};</span><span class="pln"> </span><span class="com">// this.state.selected = false;</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln"> </span><span class="com">// هذا السطر مهم، راجع الشرح أعلاه</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  select</span><span class="pun">(</span><span class="pln">event</span><span class="pun">){</span><span class="pln"> </span><span class="com">// select إضافة الدالة </span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">){</span><span class="pln"> </span><span class="com">// إزالة التحديد</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">});</span><span class="pln"> </span><span class="com">// تحديث الحالة</span><span class="pln">
    </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span><span class="pln"> </span><span class="com">// إضافة التحديد</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent</span><span class="pun">});</span><span class="pln"> </span><span class="com">// تحديث الحالة</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">   
  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div</span><span class="pun">&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MySelect</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	ولكي تحصل مكوِّنات <code>&lt;MyOption&gt;</code> على وصولٍ للدالة <code>select</code> فمررنا إشارةً مرجعيةً إليها عبر خاصيات React (‏props) من المكوِّن <code>&lt;MySelect&gt;</code> إلى المكوِّن <code>&lt;MyOption&gt;</code>. ولفعل ذلك أضفنا <code>select={this.select}</code>‎ إلى مكونات <code>&lt;MyOption&gt;</code>.
</p>

<p>
	بعد ضبط ما سبق، يمكننا إضافة <code>onClick={this.props.select}</code>‎ إلى المكوِّن <code>&lt;MyOption&gt;</code>. أرجو أن يكون واضحًا أنَّ ما فعلناه هو ربط الحدث <code>click</code> الذي سيستدعي الدالة <code>select</code>. تتكفّل React بربط دالة التعامل مع حدث النقر الحقيقي في شجرة DOM نيابةً عنّا.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9727_29" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  constructor</span><span class="pun">(){</span><span class="pln">
    super</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  select</span><span class="pun">(</span><span class="pln">event</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">){</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent</span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">   
  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MySelect</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	بعد فعلنا لذلك، يمكننا الآن ضبط الحالة بالنقر على أحد الخيارات؛ وبعبارةٍ أخرى، عندما تنقر على خيارٍ ما فستستدعى الدالة <code>select</code> وتضبط حالة المكوِّن <code>&lt;MySelect&gt;</code>. لكن مستخدم المكوِّن لن يعرف أبدًا أنَّ ذلك قد حصل لأنَّ كل ما فعلناه حتى الآن هو تغيير حالة المكوِّن، ولا توجد أي تغذية بصرية تشير إلى اختيار أي عنصر. لذا لنصلح ذلك.
</p>

<p>
	ما علينا فعله الآن هو تمرير الحالة الراهنة إلى المكوِّن <code>&lt;MyOption&gt;</code> لكي يستجيب -بصريًا- إلى تغيير حالة المكوِّن.
</p>

<p>
	باستخدام الخاصيات عبر <code>props</code>، سنُمرِّر الحالة <code>selected</code> من المكوِّن <code>&lt;MySelect&gt;</code> إلى المكوِّن <code>&lt;MyOption&gt;</code> بوضع الخاصية <code>state={this.state.selected}</code>‎ في جميع مكونات <code>&lt;MyOption&gt;</code>. أصبحنا نعلم الآن ما هي الحالة (أي <code>this.props.state</code>) والقيمة الحالية (أي <code>this.props.value</code>) للخيار لكي نتحقق إذا كانت الحالة تُطابِق القيمة الموجودة في مكوِّن <code>&lt;MyOption&gt;</code> ما. وإذا كانت تطابقها، فسنعلم أنَّه يجب تحديد هذا الخيار، وسنفعل ذلك باستخدام عبار <code>if</code> بسيطة التي تضيف أنماط تنسيق (<code>selectedStyle</code>) إلى عنصر <code>&lt;div&gt;</code> في JSX إذا كانت الحالة تُطابِق قيمة الخيار الحالي. وفيما عدا ذلك، سنعيد عنصر React مع النمط <code>unSelectedStyle</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9727_31" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  constructor</span><span class="pun">(){</span><span class="pln">
    super</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  select</span><span class="pun">(</span><span class="pln">event</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">){</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">selected</span><span class="pun">:</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent</span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">   
  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">(){</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
          display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
          padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
      </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
      </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">mySelectStyle</span><span class="pun">}&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> state</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">}</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Volvo"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> state</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">}</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Saab"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> state</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">}</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Mercedes"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">&lt;</span><span class="typ">MyOption</span><span class="pln"> state</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">}</span><span class="pln"> select</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"Audi"</span><span class="pun">&gt;&lt;/</span><span class="typ">MyOption</span><span class="pun">&gt;</span><span class="pln">
      </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
  render</span><span class="pun">(){</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> selectedStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">backgroundColor</span><span class="pun">:</span><span class="str">'red'</span><span class="pun">,</span><span class="pln"> color</span><span class="pun">:</span><span class="str">'#fff'</span><span class="pun">,</span><span class="pln">cursor</span><span class="pun">:</span><span class="str">'pointer'</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> unSelectedStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">cursor</span><span class="pun">:</span><span class="str">'pointer'</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">state</span><span class="pun">){</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">selectedStyle</span><span class="pun">}</span><span class="pln"> onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">div style</span><span class="pun">={</span><span class="pln">unSelectedStyle</span><span class="pun">}</span><span class="pln"> onClick</span><span class="pun">={</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">select</span><span class="pun">}&gt;{</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">}&lt;/</span><span class="pln">div</span><span class="pun">&gt;;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(&lt;</span><span class="typ">MySelect</span><span class="pln"> </span><span class="pun">/&gt;,</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<p>
	صحيحٌ أنَّ عنصر <code>&lt;select&gt;</code> الذي أنشأناه ليس جميلًا أو كاملًا كما كنتَ ترجو، لكنني أظن أنَّك ترى ما الغرض الذي حققناه. مكتبة React تسمح لك بالتفكير بالعناصر بطريقة منظمة ومهيكلة هيكليةً صحيحة.
</p>

<p>
	قبل الانتقال إلى شرح دور شجرة DOM الافتراضية، أود أنَّ أوضِّح أنَّه من غير الضروري استخدام JSX و Babel. يمكنك تخطي هذه الأدوات واستخدام شيفرات JavaScript مباشرة. سأريك نسخةً أخيرةً من الشيفرة بعد تحويل JSX باستخدام Babel. إذا لم ترغب باستخدام JSX فيمكنك أن تكتب الشيفرة الآتية يدويًا بدلًا من الشيفرة التي كتبناها خلال هذا المقال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9727_33" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MySelect</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  constructor</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    super</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  select</span><span class="pun">(</span><span class="pln">event</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">
        selected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">false</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">setState</span><span class="pun">({</span><span class="pln">
        selected</span><span class="pun">:</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">target</span><span class="pun">.</span><span class="pln">textContent
      </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> mySelectStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      border</span><span class="pun">:</span><span class="pln"> </span><span class="str">'1px solid #999'</span><span class="pun">,</span><span class="pln">
      display</span><span class="pun">:</span><span class="pln"> </span><span class="str">'inline-block'</span><span class="pun">,</span><span class="pln">
      padding</span><span class="pun">:</span><span class="pln"> </span><span class="str">'5px'</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"div"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      style</span><span class="pun">:</span><span class="pln"> mySelectStyle
    </span><span class="pun">},</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MyOption</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      state</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">,</span><span class="pln">
      select</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">,</span><span class="pln">
      value</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Volvo"</span><span class="pln">
    </span><span class="pun">}),</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MyOption</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      state</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">,</span><span class="pln">
      select</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">,</span><span class="pln">
      value</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Saab"</span><span class="pln">
    </span><span class="pun">}),</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MyOption</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      state</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">,</span><span class="pln">
      select</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">,</span><span class="pln">
      value</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Mercedes"</span><span class="pln">
    </span><span class="pun">}),</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MyOption</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      state</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">state</span><span class="pun">.</span><span class="pln">selected</span><span class="pun">,</span><span class="pln">
      select</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">select</span><span class="pun">,</span><span class="pln">
      value</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Audi"</span><span class="pln">
    </span><span class="pun">}));</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyOption</span><span class="pln"> extends </span><span class="typ">React</span><span class="pun">.</span><span class="typ">Component</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  render</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> selectedStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      backgroundColor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'red'</span><span class="pun">,</span><span class="pln">
      color</span><span class="pun">:</span><span class="pln"> </span><span class="str">'#fff'</span><span class="pun">,</span><span class="pln">
      cursor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'pointer'</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> unSelectedStyle </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      cursor</span><span class="pun">:</span><span class="pln"> </span><span class="str">'pointer'</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value </span><span class="pun">===</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">state</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"div"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        style</span><span class="pun">:</span><span class="pln"> selectedStyle</span><span class="pun">,</span><span class="pln">
        onClick</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">select
      </span><span class="pun">},</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="str">"div"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        style</span><span class="pun">:</span><span class="pln"> unSelectedStyle</span><span class="pun">,</span><span class="pln">
        onClick</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">select
      </span><span class="pun">},</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">props</span><span class="pun">.</span><span class="pln">value</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">};</span><span class="pln">
</span><span class="typ">ReactDOM</span><span class="pun">.</span><span class="pln">render</span><span class="pun">(</span><span class="typ">React</span><span class="pun">.</span><span class="pln">createElement</span><span class="pun">(</span><span class="typ">MySelect</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">),</span><span class="pln"> document</span><span class="pun">.</span><span class="pln">getElementById</span><span class="pun">(</span><span class="str">'app'</span><span class="pun">));</span></pre>

<h2>
	فهم دور شجرة DOM الافتراضية (virtual DOM)
</h2>

<p>
	سأنهي جولتنا بأكثر جوانب React حديثًا بين المطورين، إذ سأتحدث عن شجرة DOM الافتراضية (React virtual DOM).
</p>

<p>
	لاحظنا -عبر الأمثلة في هذا المقال- أنَّ التعامل الوحيد مع شجرة DOM الحقيقية أثناء إنشائنا لعنصر <code>&lt;select&gt;</code> خاص بنا هو عندما أخبرنا الدالة <code>ReactDOM.render()</code>‎ أين ستعرض مكوِّنات UI في صفحة HTML (أي عندما عرضناها في <code>&lt;div id="app"&gt;&lt;/div&gt;</code>). من المرجح أن يكون هذا تعاملك الوحيد مع شجرة DOM الحقيقية عندما تبني تطبيق React من شجرة من المكوِّنات. وهنا تأتي قيمة مكتبة React. فعند استخدامك لها، ليس عليك أن تفكر بشجرة DOM بنفس الطريقة التي كنتَ تفكِّر فيها عند كتابتك لشيفرة jQuery. فمكتبة React تستبدل jQuery عبر تجريد استخدام شجرة DOM.
</p>

<p>
	ولأنَّ شجرة DOM الافتراضية حلّت محل شجرة DOM الحقيقية، سمح ذلك بإجراء تحديثات لشجرة DOM الحقيقية مع أداءٍ ممتاز. تبقي شجرة DOM الافتراضية سجلًا بجميع التغيرات في واجهة المستخدم اعتمادًا على الحالة والخاصيات (<code>state</code> و <code>props</code>)، ثم تقارنها بشجرة DOM الحقيقية وتجري أقل مقدار ممكن من التعديلات عليها. بصيغةٍ أخرى، لا تُحدَّث شجرة DOM الحقيقية إلا بأقل قدر ممكن وذلك عند تغيير الحالة أو الخاصيات.
</p>

<p>
	صراحةً، هذا المفهوم ليس ثوريًا أو جديدًا، يمكنك فعل المثل باستخدام شيفرة jQuery مكتوبة بعناية، لكنك لن تحتاج إلى التفكير بهذه الأمور عند استخدام React. فشجرة DOM الافتراضية تجري عمليات تحسين الأداء عوضًا عنك، فلا حاجة لأن تقلق حول أي شيء، فكل ذلك يحدث وراء الكواليس ونادرًا ما تحتاج إلى التعامل مع شجرة DOM الحقيقية نفسها.
</p>

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

<p>
	تذكر <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20react/" rel="">هذه السلسلة</a> عندما تريد أن تعرِّف ما هي React. مكتبة React.js هي مكتبة JavaScript التي يمكن استخدامها لبناء واجهات المستخدم، وباستخدام React يمكن للمطورين إنشاء مكونات قابلة لإعادة الاستخدام، وهذه المكونات تُظهِر البيانات وتستطيع تغييرها مع الزمن؛ وتوجد أيضًا مكتبة React Native لبناء تطبيقات للهواتف الذكية باستخدام React.
</p>

<p>
	ترجمة وبتصرف للفصل <a href="%5Bhttps://www.reactenlightenment.com/what-is-react.html%5D(https://www.reactenlightenment.com/what-is-react.html)" rel="">What is React?</a>‎ من كتاب <a href="https://www.reactenlightenment.com/" rel="external nofollow">React Enlightenment</a>
</p>
]]></description><guid isPermaLink="false">773</guid><pubDate>Wed, 08 Jan 2020 18:00:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; React.js - &#x645;&#x643;&#x62A;&#x628;&#x629; &#x62A;&#x637;&#x648;&#x64A;&#x631; &#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x627;&#x62A; &#x627;&#x644;&#x631;&#x633;&#x648;&#x645;&#x64A;&#x629; &#x645;&#x646; &#x641;&#x64A;&#x633; &#x628;&#x648;&#x643;</title><link>https://academy.hsoub.com/programming/javascript/react/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-reactjs-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%85%D9%86-%D9%81%D9%8A%D8%B3-%D8%A8%D9%88%D9%83-r112/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_06/react-intro.png.ee82280dfd1c75a62a50858da73a5337.png" /></p>

<div id="wmd-preview-section-60"><p>يعتبر React.js -على حداثته- من أقوى أطر عمل Javascript (بعضهم قد يسميه مكتبة وليس إطار عمل) لبناء الواجهات الرسومية على الويب، حيث طبّق أفكارًا جديدة في هذا المجال، جعلت شِفرة الواجهات البرمجية أكثر نظافة، سرعة وأكثر قابلية للصيانة. يسمح لك React ببناء الواجهة الرسومية في مجموعة مكونات، كل مكوّن عبارة عن سرد لهيكلة ومنطق المكون، إذا تمزج بين شِفرة HTML مخصصّة وشِفرة جافاسكربت تصف سلوك ذاك المكون، ليكون قائما بذاته وقابلا لإعادة الاستعمال.</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" style="line-height: 22.3999996185303px; text-align: center;" href="https://academy.hsoub.com/uploads/monthly_2015_06/react-intro.png.faedf062411e6e0c1ae51ab7f74fbd37.png"><img data-fileid="3124" class="ipsImage ipsImage_thumbnailed" src="https://academy.hsoub.com/uploads/monthly_2015_06/react-intro.thumb.png.281e4107933e768579c69ed6b167511d.png" alt="react-intro.thumb.png.281e4107933e768579"></a></p><p>إطار عمل React مُطور من طرف شركة فيس بوك (Facebook)، وقد يكفيك ثقة ويجذب انتباهك بمجرد أن تعرف أن فيس بوك نفسها تستخدم React في واجهتها البرمجية على موقع Facebook نفسه! يمكنك فتح موقع Facebook وعرض شفرة HTML الخاصة به والبحث عن كلمة react للتأكد بنفسك.</p><p id="درس-حول-كيفية-إنشاء-مربع-تعليقات-بسيط-باستخدام-react">سنقوم في هذا الدرس بإنشاء مُربَّع تعليقات بسيط وفعَّال بإمكانك وضعه في مدوَّنتك، سيكون المُربَّع عبارة عن نُسخة مُجرَّدة من التعليقات الآنية التي تُقدمها لك تعليقات Disquse ،LiveFyre أو فيس بوك.</p><p>ستجد في نهاية الدَّرس أنَّ لديكَ مُربَّع تعليقات يوفِّر ما يلي:</p><ul><li>عرض لجميع التعليقات.</li><li>نموذج لإرسال تعليق.</li><li>خُطَّافات لتوفير مُنتهى خلفي مُخصَّص custom backend.</li></ul><p>سوف يحتوي مُربَّع التعليقات كذلك على بعض المزايا اللَّطيفة:</p><ul><li>تعليق مُحسَّن: تظهر التَّعليقات في القائمة قبل أن يتمّ حفظها على الخادم وبناءً عليه تظهر التَّعليقات في التوِّ واللَّحظة.</li><li>تحديثات حيَّة: تظهر تعليقات المستخدمين الآخرين في عرض التَّعليقات في نفس وقت الإرسال.</li><li>هيئة Markdown: يُمكن للمستخدمين استخدام Markdown لتهيئة نصوصهم.</li></ul><p>هل ترغب في تخطِّي كل هذا ومعاينة المصدر؟ <a rel="external nofollow" href="https://github.com/reactjs/react-tutorial">كل شيء موجود على GitHub.</a></p></div><div id="wmd-preview-section-61"><h2 id="تشغيل-الخادم">تشغيل الخادم</h2><p>رغم أنَّه ليس من الضروري أن تبدأ بهذا الجزء من الدرس إلَّا أنَّنا سنقوم في وقت لاحق بإضافة وظائف تتطلَّب المُشاركة <span style="font-family:courier new,courier,monospace;">POST</span> إلى خادم قيد التشغيل. إذا كُنتَ واثقٌ من أنّك على دراية بهذا الأمر وترغب في إنشاء خادمك الخاص يُمكنكَ القيام بذلك. ولِمَن يُريد التَّركيز على تعلُّم React دون الحاجة إلى القلق بشأن جوانب الخادم، فلقد كتبنا خوادم بسيطة بعددٍ من اللُّغات: <span style="line-height: 22.3999996185303px;">Python ،Ruby ،Go، Node.js و PHP.</span></p><p>كلُّ هذا مُتاح على GitHub. يُمكن <a rel="external nofollow" href="https://github.com/reactjs/react-tutorial/">الاطِّلاع على المصدر</a> أو <a rel="external nofollow" href="https://github.com/reactjs/react-tutorial/archive/master.zip">تحميل ملفّ مضغوط</a> للبدء.</p><p>للبدء بتطبيق هذا الدَّرس، كلّ ما عليكَ فعله هو بداية تحرير <span style="font-family:courier new,courier,monospace;">public/index.php</span>.</p></div><div id="wmd-preview-section-62"><h2 id="البدء">البدء</h2><p>سنستخدم لهذا الدرس ملفَّات JavaScript سبق إنشاؤها على شبكة توصيل مُحتوى CDN. قم بفتح المُحرِّر المفضَّل لديك وقم بإنشاء مُستند HTML جديد:</p><pre data-pbcklang="html" data-pbcktabsize="" class="html ipsCode prettyprint">&lt;!-- index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Hello React&lt;/title&gt;
    &lt;script src="https://fb.me/react-0.13.3.js"&gt;&lt;/script&gt;
    &lt;script src="https://fb.me/JSXTransformer-0.13.3.js"&gt;&lt;/script&gt;
    &lt;script src="https://code.jquery.com/jquery-2.1.3.min.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id="content"&gt;&lt;/div&gt;
    &lt;script type="text/jsx"&gt;
      // Your code here
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre><p>سيتمّ كتابة شفرات JavaScript في وسم السكربت هذا طوال الفترة المتبقية من الدرس.</p><p><strong>مُلاحظة:  </strong>قُمنا بإدراج jQuery هُنا لأننا نٌريد تبسيط الشَّفرات لاستدعاءات Ajax في المُستقبل، ولكنَّها ليست إلزاميَّة لعمل React.</p></div><div id="wmd-preview-section-63"><h2 id="مكونك-الأول">مُكوِّنكَ الأوَّل</h2><p>تتمحور الفكرة الأساسيَّة لـ React حول كل شيءٍ له علاقة بالمُكوِّنات التركيبيَّة القابلة للتَّشكيل modular, composable components. سنستخدم بنية المُكوٍّنات التالية لمثال مُربَّع التَّعليقات لهذا الدرس:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">- CommentBox
  - CommentList
    - Comment
  - CommentForm</pre><p>سنقوم الآن ببناء المُكوِّن CommentBox وما هو إلَّا وسم بسيط:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial1.js
var CommentBox = React.createClass({
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        Hello, world! I am a CommentBox.
      &lt;/div&gt;
    );
  }
});
React.render(
  &lt;CommentBox /&gt;,
  document.getElementById('content')
);</pre><p>لاحظ أن أسماء عناصر HTML تبدأ بحرف صغير في حين أن أسماء فئات React تبدأ بحرف كبير.</p></div><div id="wmd-preview-section-64"><h3 id="1-صياغة-jsx">1. صياغة JSX</h3><p>ستُلاحظ أوَّل ما تلاحظ تلكَ الصياغة المُشابهة لـ XML في شفرة JavaScript. لدينا precompiler بسيط يُترجم الجُملة البسيطة Syntactic Sugar إلى شفرات JavaScript المُجرَّدة هذه:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial1-raw.js
var CommentBox = React.createClass({displayName: 'CommentBox',
  render: function() {
    return (
      React.createElement('div', {className: "commentBox"},
        "Hello, world! I am a CommentBox."
      )
    );
  }
});
React.render(
  React.createElement(CommentBox, null),
  document.getElementById('content')
);</pre><p>إنَّ استخدام صياغة JSX اختياري ولكن وجدنا أنَّها أسهل استخدامًا من شفرات JavaScript مُجرَّدة. يُمكن قراءة المزيد في <a rel="external nofollow" href="https://facebook.github.io/react/docs/jsx-in-depth.html">مقال صياغة JSX</a></p></div><div id="wmd-preview-section-65"><h3 id="2-ماذا-يحدث-هنا">2. ماذا يحدث هنا</h3><p>نقوم بتمرير بعض الوظائف في كائن JavaScript إلى دالَّة <span style="font-family:courier new,courier,monospace;">()React.createClass</span> لإنشاء مُكوِّن React جديد. أهم هذه الوظائف ما تُسمَّى تصيير render والتي تُعيد شجرة من مُكوِّنات React والتي في نهاية المطاف ستقوم بالتصيير عبر HTML.</p><p>لا تُعتبر وسوم عُقَد نموذج كائن مُستند DOM فعليَّة، وإنَّما هي تمثيلات من مُكوِّنات div الخاصَّة بـ React. يُمكنكَ اعتبارها كوسوم أو قطع من البيانات والتي يعرف React كيفيَّة التعامل معها. React آمن. لا نقوم بتوليد سلاسل HTML لذلك فإن حماية XSS تُعتبر الافتراضيَّة.</p><p>لا يجب عليكَ إعادة شفرات HTML قياسيَّة. وإنَّما يُمكنكَ إعادة شجرة من المُكوِّنات التي قُمتَ (أو شخص آخر قام) ببنائها. هذا ما يجعل React قابلة للتَّشكيل composable: وهي عقيدة أساسيَّة في الواجهات الأماميَّة القابلة للصّيانة.</p><p>يقوم <span style="font-family:courier new,courier,monospace;">()React.render</span> بتمثيل المُكوِّن القاعدي، بدء عمل الإطار، ثم إدخال الوسوم إلى عنصر نموذج كائن مُستند خام، يتمّ تقديم تلك الوسوم كمُعطى ثاني .</p></div><div id="wmd-preview-section-66"><h2 id="تركيب-المكونات">تركيب المُكوِّنات</h2><p>سنُنشيء الآن هياكل بناء لكلٍّ من المُكوِّنين CommentList وCommentForm والتي ستكون -مرَّة أخرى- عبارة عن وسوم بسيطة. أضِف هذين المُكوِّنين إلى ملفِّك مع الحفاظ على تعريف  commentBox الحالي واستدعاء React.render:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial2.js
var CommentList = React.createClass({
  render: function() {
    return (
      &lt;div className="commentList"&gt;
        Hello, world! I am a CommentList.
      &lt;/div&gt;
    );
  }
});

var CommentForm = React.createClass({
  render: function() {
    return (
      &lt;div className="commentForm"&gt;
        Hello, world! I am a CommentForm.
      &lt;/div&gt;
    );
  }
});</pre><p>ما سنقوم بعمله الآن هو تحديث مُكوِّن CommentBox لاستخدام المُكوِّنات الجديدة:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial3.js
var CommentBox = React.createClass({
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList /&gt;
        &lt;CommentForm /&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>لاحظ كيف تمَّ مزج وسوم HTML والمُكوِّنات التي قُمنا ببنائها. إنَّ مُكوِّنات HTML ما هي إلَّا مُكوِّنات React مُنتظمة، تمامًا مثل تلك التي تقوم بتعريفها ولكن مع فارق واحد. سيقوم مترجم JSX تلقائيًا بإعادة كتابة وسوم HTML إلى تعبيرات <span style="font-family:courier new,courier,monospace;">React.createElement()</span> tagName وترك كل شيء على حدة. وهذا لمنع حدوث التَّلوّث في مساحة الاسم العموميَّة global namespace.</p></div><div id="wmd-preview-section-67"><h2 id="استخدام-الخصائص">استخدام الخصائص</h2><p>سنقوم الآن بانشاء مُكوِّن Comment، والذي سوف يعتمد على البيانات التي تمَّ تمريرها إليه من المُكوِّن الأساسي. يتمّ اتاحة البيانات التي تمّ تمريرها من مُكوِّن أساسي كـ "خاصيَّة" في المُكوِّن الفرعي. ويتمّ الوصول إلى هذه "الخصائص" من خلال <span style="font-family:courier new,courier,monospace;">this.props</span>. يُمكننا باستخدام الخصائص props قراءة البيانات التي تمّ تمريرها إلى Comment من CommentList، وتصيير بعض الترميزات:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial4.js
var Comment = React.createClass({
  render: function() {
    return (
      &lt;div className="comment"&gt;
        &lt;h2 className="commentAuthor"&gt;
          {this.props.author}
        &lt;/h2&gt;
        {this.props.children}
      &lt;/div&gt;
    );
  }
});</pre><p>يُمكنكَ وضع نصّ أو مُكوِّنات React في الشَّجرة وذلك بإحاطة تعبير JavaScript بأقواس داخل JSX (إما كخاصيَّة أو كمُكوِّن فرعي). نقوم بالوصول إلى خاصيَّات مُسمَّاه تمّ تمريرها إلى عنصر كمفاتيح على <span style="font-family:courier new,courier,monospace;">this.props </span>وأيّ عناصر مُتداخلة كما <span style="font-family:courier new,courier,monospace;">this.props.children.</span></p></div><div id="wmd-preview-section-68"><h2 id="خصائص-المكون">خصائص المُكوِّن</h2><p>نحتاج الآن وبعد أن قمنا بتحديد مُكوِّن Comment إلى تمرير اسم الكاتب ونصّ التعليق إلى هذا المُكوِّن. يسمح لنا هذا بإعادة استخدام نفس الشَّفرة لكلِّ تعليق مُختلف. لنقوم الآن بإضافة بعض التَّعليقات داخل مُكوِّن CommentList:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial5.js
var CommentList = React.createClass({
  render: function() {
    return (
      &lt;div className="commentList"&gt;
        &lt;Comment author="Pete Hunt"&gt;This is one comment&lt;/Comment&gt;
        &lt;Comment author="Jordan Walke"&gt;This is *another* comment&lt;/Comment&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>لاحظ أنَّنا قد قُمنا بتمرير بعض البيانات من مُكوِّن CommentList الأساسي إلى مُكوِّنات Comment الفرعيَّة. مرَّرنا على سبيل المثال Pete Hunt (عن طريق خاصيَّة) وThis is one comment (عن طريق عُقدة فرعيَّة تُشبه XML) إلى Comment الأوَّل. وكما ذكرنا بالأعلى فإنَّ مُكوِّن Comment سيعمل على الوصول إلى هذه الخصائص من خلال <span style="font-family:courier new,courier,monospace;">this.props.author</span>، و<span style="font-family:courier new,courier,monospace;">this.props.children</span>.</p></div><div id="wmd-preview-section-69"><h2 id="إضافة-markdown">إضافة Markdown</h2><p>Markdown هي طريقة بسيطة لتهيئة مُضمّنة inline لنصِّك. على سبيل المثال، احاطة النص بعلامة النجمة (*) سيقوم بتأكيده.</p><p>أولًا، أضِف مكتبة الطرف الثالث marked إلى تطبيقك. Marked هي مكتبة JavaScript تقوم بأخذ نص Markdown وتُحوِّله إلى صيغة HTML خام. هذا الأمر يتطلَّب وسم سكربت في قسم head (قُمنا بادراجه بالفعل في أرضيَّة React):</p><pre data-pbcklang="html" data-pbcktabsize="" class="html ipsCode prettyprint">&lt;!-- index.html --&gt;
&lt;head&gt;
  &lt;title&gt;Hello React&lt;/title&gt;
  &lt;script src="https://fb.me/react-0.13.3.js"&gt;&lt;/script&gt;
  &lt;script src="https://fb.me/JSXTransformer-0.13.3.js"&gt;&lt;/script&gt;
  &lt;script src="https://code.jquery.com/jquery-2.1.3.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"&gt;&lt;/script&gt;
&lt;/head&gt;</pre><p>سنقوم بعد ذلك بتحويل نصّ التَّعليق إلى Markdown ومن ثمَّ إخراجه:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial6.js
var Comment = React.createClass({
  render: function() {
    return (
      &lt;div className="comment"&gt;
        &lt;h2 className="commentAuthor"&gt;
          {this.props.author}
        &lt;/h2&gt;
        {marked(this.props.children.toString())}
      &lt;/div&gt;
    );
  }
});</pre><p>كل ما فعلناه هنا هو استدعاء مكتبة marked. نحتاج إلى تحويل <span style="font-family:courier new,courier,monospace;">this.props.children </span>من نصّ React مُحاط إلى سلسلة خام يُمكن لمكتبة marked فهمها ولذلك فإننا نقوم بستدعاء دالَّة <span style="font-family:courier new,courier,monospace;">()toString</span>.</p><p>لكن لدينا مشكلة وهي أنَّه يتمّ إظهار وسوم HTML الموجودة في التَّعليقات بالشكل التَّالي في المُتصفح: This is another comment.</p><p>هذا الأمر هو حماية React لك من <a rel="external nofollow" href="https://en.wikipedia.org/wiki/Cross-site_scripting">هجوم XSS</a>. هُناك طريقة للالتفاف على ذلك، ولكنَّ إطار العمل يُحذِّرُكَ من استخدامها:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial7.js
var Comment = React.createClass({
  render: function() {
    var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
    return (
      &lt;div className="comment"&gt;
        &lt;h2 className="commentAuthor"&gt;
          {this.props.author}
        &lt;/h2&gt;
        &lt;span dangerouslySetInnerHTML={{__html: rawMarkup}} /&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>هذه الشَّفرات هي <abbr title="واجهة برمجية | Application Programming Interface">API</abbr> خاصّ والذي عمدًا يجعل من الصَّعب إدراج شفرات HTML خام، في حالتنا بالنِّسبة لمكتبة marked فإنَّنا سنقوم بالاستفادة من هذا المنفذ الخلفيّ.</p><p>تذكَّر: باستخدامك لهذه الميزة فإنَّك تعتمد على مكتبة marked أن تكون آمنة. نقوم في هذه الحالة بتمرير sanitize: true التي تطلب من مكتبة marked تنفيذ أي وسم HTML في المصدر بدلًا من تمريره دون تغيير.</p></div><div id="wmd-preview-section-70"><h2 id="إضافة-نموذج-البيانات">إضافة نموذج البيانات</h2><p>حتَّى الآن فإنَّنا نقوم بإدراج تعليقات مُباشرة في شفرات المصدر. بدلًا من ذلك، سنقوم بتصيير بضع من بيانات JSON في قائمة التعليق. يأتي هذا من الخادم في نهاية المطاف، ولكن في الوقت الراهن سنكتبها نحن في المصدر:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial8.js
var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];</pre><p>الآن نحنُ بحاجة إلى إدخال هذه البيانات في مُكوِّن CommentList بطريقة نموذجيِّة. قُم بتعديل CommentBox واستدعاء <span style="font-family:courier new,courier,monospace;">()React.render </span>لتمرير هذه البيانات إلى CommentList عن طريق الخصائص props:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial9.js
var CommentBox = React.createClass({
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.props.data} /&gt;
        &lt;CommentForm /&gt;
      &lt;/div&gt;
    );
  }
});

React.render(
  &lt;CommentBox data={data} /&gt;,
  document.getElementById('content')
);</pre><p>الآن حيثُ أنَّ البيانات مُتاحة في CommentList، سوف نقوم بتقديم التَّعليقات بطريقة ديناميكيَّة:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial10.js
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        &lt;Comment author={comment.author}&gt;
          {comment.text}
        &lt;/Comment&gt;
      );
    });
    return (
      &lt;div className="commentList"&gt;
        {commentNodes}
      &lt;/div&gt;
    );
  }
});</pre><p>هذا كل شيء.</p></div><div id="wmd-preview-section-71"><h2 id="الاستدعاء-من-الخادم">الاستدعاء من الخادم</h2><p>سنعمل الآن على استبدال البيانات الثَّابتة ببعض البيانات الديناميكيَّة من الخادم. يتمّ ذلك بإزالة خاصيَّة البيانات data prop واستبدالها بعنوان URL للجلب:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial11.js
React.render(
  &lt;CommentBox url="comments.json" /&gt;,
  document.getElementById('content')
);</pre><p>هذا المُكوِّن مُختلف عن المُكوِّنات السَّابقة حيثُ أنَّه سيضطر إلى إعادة تصيير نفسه. لن يحتوي المُكوِّن على أيّ بيانات إلى أن يعود الطَّلب من الخادم، في هذه الحالة قد يحتاج المُكوِّن إلى تصيير بعض التَّعليقات الجديدة.</p></div><div id="wmd-preview-section-72"><h2 id="الحالة-التفاعلية">الحالة التفاعليَّة</h2><p>قام كلّ مُكوِّن حتَّى الآن على أساس خصائصه بتصيير نفسه مرة واحدة. الخصائص props ثابتة: يتمّ تمريرها من المُكوِّن الأساسي و”مملوكة” من قبل المُكوِّن الأساسي كذلك. لتنفيذ التَّفاعلات، فإنَّنا نُقدِّم حالة قابلة للتغيير إلى المُكوِّن. حالة this.state هي خاصَّة بالمُكوِّن ويُمكن تغييرها من خلال استدعاء <span style="font-family:courier new,courier,monospace;">()this.setState </span>يقوم المُكوِّن بإعادة تقديم نفسه عند تحديث الحالة.</p><p>وظائف<span style="font-family:courier new,courier,monospace;"> ()render</span> مكتوبة إلزاميًّا كدوال <span style="font-family:courier new,courier,monospace;">this.props</span> و<span style="font-family:courier new,courier,monospace;">this.state</span>. يضمن إطار العمل أن تكون واجهة المستخدم دائمًا مُتَّسِقَة مع المُدخَلات.</p><p>عندما يقوم الخادم بجلب بيانات سنقوم نحن بتغيير بيانات التعليق لدينا. لنُضيف الآن مصفوفة من بيانات التَّعليق كحالة للمُكوِّن CommentBox:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial12.js
var CommentBox = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm /&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>يتمّ تنفيذ دالَّة<span style="font-family:courier new,courier,monospace;"> ()getInitialState</span> مرَّة واحدة فقط خلال دورة حياة المُكوِّن كما أنَّها تبدأ الحالة الأوليَّة للمُكوِّن.</p></div><div id="wmd-preview-section-73"><h2 id="تحديث-الحالة">تحديث الحالة</h2><p>نُريد عند إنشاء المُكوِّن لأوَّل مرَّة أن نحصل على (GET) بعض بيانات JSON من الخادم وتحديث الحالة لتعكس أحدث البيانات. هذا من شأنه أن يكون نقطة نهاية ديناميكيَّة لو كان الأمر في تطبيق حقيقي، ولكن سنستخدم لهذا المثال ملف JSON ثابت لابقاء الأمور بسيطة:</p><pre data-pbcklang="" data-pbcktabsize="" class="ipsCode prettyprint">// tutorial13.json
[
  {"author": "Pete Hunt", "text": "This is one comment"},
  {"author": "Jordan Walke", "text": "This is *another* comment"}
]</pre><p>سنقوم باستخدام مكتبة jQuery للمساعدة في عمل طلب غير متزامن asynchronous request إلى الخادم.</p><p>مُلاحظة: حيثُ أنَّ هذا الأمر أصبح تطبيق AJAX فإنَّك سوف تحتاج لتطوير تطيبقك باستخدام خادم ويب بدلًا من أن ملف موجود في نظام ملفاتك. قدَّمنا -كما هو مذكورٌ بالأعلى- العديد من الخوادم التي يُمكنكَ استخدامها <a rel="external nofollow" href="https://github.com/reactjs/react-tutorial/">على GitHub</a>. توفر تلك الخوادم التأدية الوظيفيَّة التي تحتاجها لبقيَّة هذا الدرس.</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial13.js
var CommentBox = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm /&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>وظيفة componentDidMount هنا هي وظيفة تُستدعى تلقائيًا بواسطة React عندما يتمّ تصيير مُكوِّن. مفتاح التَّحديثات الديناميكيَّة هو استدعاء دالَّة <span style="font-family:courier new,courier,monospace;">()this.setState</span>. نقوم باستبدال مصفوفة التَّعليقات القديمة بواحدة جديدة من الخادم وتقوم واجهة المستخدم بتحديث نفسها تلقائيًا. بسبب هذا التفاعل، يُعتبر التغيير لإضافة تحديثات حيَّة طفيفًا. سوف نستخدم أسلوب بسيط في هذا الدَّرس ولكن لكَ الحُريَّة في استخدام WebSockets أو غيرها من التكنولوجيَّات.</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial14.js
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm /&gt;
      &lt;/div&gt;
    );
  }
});

React.render(
  &lt;CommentBox url="comments.json" pollInterval={2000} /&gt;,
  document.getElementById('content')
);</pre><p>كل ما فعلناه هنا هو نقل استدعاء AJAX إلى وظيفة مُستقلَّة واستدعائها عند تحميل المُكوِّن الأوَّل واستدعائها كلّ ثانيتين بعد ذلك. حاول تشغيل هذا في مُتصفِّحك وتغيير ملف <span style="font-family:courier new,courier,monospace;">comments.json</span>. في غضون ثانيتين ستظهر لكَ التغييرات.</p></div><div id="wmd-preview-section-74"><h2 id="إضافة-تعليقات-جديدة">إضافة تعليقات جديدة</h2><p>حان الآن الوقت لبناء النموذج. على مُكوِّن CommentForm أن يسأل المُستخدم عن اسمه ونصّ التَّعليق، ثم يقوم بإرسال طلب إلى الخادم لحفظ التعليق.</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial15.js
var CommentForm = React.createClass({
  render: function() {
    return (
      &lt;form className="commentForm"&gt;
        &lt;input type="text" placeholder="Your name" /&gt;
        &lt;input type="text" placeholder="Say something..." /&gt;
        &lt;input type="submit" value="Post" /&gt;
      &lt;/form&gt;
    );
  }
});</pre><p>دعونا نجعل النموذج متجاوب. عندما يقوم المُستخدم بإرسال النَّموذج، يجب علينا مسحه clear، تقديم طلب إلى الخادم، ثُمَّ تحديث قائمة التعليقات. للبدء في تنفيذ هذا، سقوم بالاستماع إلى حدث ارسال النَّموذج ومسحه.</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial16.js
var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = React.findDOMNode(this.refs.author).value.trim();
    var text = React.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    // TODO: send request to the server
    React.findDOMNode(this.refs.author).value = '';
    React.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function() {
    return (
      &lt;form className="commentForm" onSubmit={this.handleSubmit}&gt;
        &lt;input type="text" placeholder="Your name" ref="author" /&gt;
        &lt;input type="text" placeholder="Say something..." ref="text" /&gt;
        &lt;input type="submit" value="Post" /&gt;
      &lt;/form&gt;
    );
  }
});</pre></div><div id="wmd-preview-section-75"><h3 id="1-الأحداث-events">1- الأحداث Events</h3><p>تقوم React بإرفاق مُعالجات الحدث في المُكوِّنات باستخدام اتفاقية التَّسمية camelCase. نقوم بإرفاق مُعالج onSubmit إلى النَّموذج الذي يعمل على مسح حقول النَّموذج عند إرساله مع إدخال صحيح.</p><p>عليكَ استدعاء<span style="font-family:courier new,courier,monospace;"> ()preventDefault</span> بالحدث لمنع الإجراء الافتراضي للمُتصفِّح من اعتماد النَّموذج.</p></div><div id="wmd-preview-section-76"><h3 id="2-المراجع-refs">2- المراجع Refs</h3><p>نستخدم خاصيَّة ref لتعيين اسم للمُكوِّن الفرعي وthis.refs لارجاع المُكوِّن. يمكن أن نستدعي<span style="font-family:courier new,courier,monospace;"> (React.findDOMNode(component</span>على مُكوّن للحصول على عنصر نموذج كائن مُستند المُتصفِّح الأصلي.</p></div><div id="wmd-preview-section-77"><h3 id="3-نداءات-الخصائص">3- نداءات الخصائص</h3><p>عندما يُرسِل المُستخدم التَّعليق، فإنَّنا سوف تحتاج إلى تحديث قائمة التَّعليقات لتشمل التَّعليق الجديد. من الطبيعي أن تفعل كل هذا في مُكوِّن CommentBox حيث أنَّ المُكوِّن يمتلك الحالة التي تُمثِّل قائمة التَّعليقات.</p><p>نحن بحاجة لتمرير البيانات من نُسخة المُكوِّن الفرعي الاحتياطيَّة إلى المُكوِّن. يتمّ فعل هذا في وظيفة render الخاصَّة بالأب عن طريق تمرير رد نداء جديد (handleCommentSubmit) في الابن ثُمَّ الزامها لحدث الابن onCommentSubmit. كُلَّما تم تشغيل الحدث، سيُنفَّذ الاستدعاء:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial17.js
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleCommentSubmit: function(comment) {
    // TODO: submit to the server and refresh the list
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm onCommentSubmit={this.handleCommentSubmit} /&gt;
      &lt;/div&gt;
    );
  }
});</pre><p>سوف نستدعي الآن النِّداء من CommentForm عندما يقوم المُستخدم بإرسال النَّموذج:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial18.js
var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = React.findDOMNode(this.refs.author).value.trim();
    var text = React.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    this.props.onCommentSubmit({author: author, text: text});
    React.findDOMNode(this.refs.author).value = '';
    React.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function() {
    return (
      &lt;form className="commentForm" onSubmit={this.handleSubmit}&gt;
        &lt;input type="text" placeholder="Your name" ref="author" /&gt;
        &lt;input type="text" placeholder="Say something..." ref="text" /&gt;
        &lt;input type="submit" value="Post" /&gt;
      &lt;/form&gt;
    );
  }
});</pre><p>الآن وبعد أن أصبح النِّداء في مكانه الصحيح، كل ما علينا القيام به هو الإرسال إلى الخادم وتحديث القائمة:</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial19.js
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleCommentSubmit: function(comment) {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm onCommentSubmit={this.handleCommentSubmit} /&gt;
      &lt;/div&gt;
    );
  }
});</pre></div><div id="wmd-preview-section-78"><h2 id="تحديثات-محسنة">تحديثات مُحسَّنة</h2><p>مشروعنا الآن كامل الوظائف ولكن من المُمل أن نقوم بانتظار الطَّلب حتَّى يكتمل قبل ظهور تعليقك في القائمة. يُمكننا إضافة هذا التَّعليق إلى القائمة لجعل التطبيق يعمل بشكلٍ أسرع.</p><pre data-pbcklang="javascript" data-pbcktabsize="" class="javascript ipsCode prettyprint">// tutorial20.js
var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleCommentSubmit: function(comment) {
    var comments = this.state.data;
    var newComments = comments.concat([comment]);
    this.setState({data: newComments});
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      &lt;div className="commentBox"&gt;
        &lt;h1&gt;Comments&lt;/h1&gt;
        &lt;CommentList data={this.state.data} /&gt;
        &lt;CommentForm onCommentSubmit={this.handleCommentSubmit} /&gt;
      &lt;/div&gt;
    );
  }
});</pre></div><div id="wmd-preview-section-79"><h2 id="ختاما">ختامًا</h2><p>انتهيتَ لتوك من إنشاء مربع تعليقات في بضع خطوات بسيطة. يُمكنك الآن التَّعرُّف على المزيد حول <a rel="external nofollow" href="https://facebook.github.io/react/docs/why-react.html">أسباب استخدام React</a>، أو الخوض في <a rel="external nofollow" href="https://facebook.github.io/react/docs/top-level-api.html">مراجع <abbr title="واجهة برمجية | Application Programming Interface">API</abbr></a> وبدء العمل.</p><p>ترجمة -وبتصرّف- للمقال: <a rel="external nofollow" href="https://facebook.github.io/react/docs/tutorial.html">Tutorial | React</a>.</p></div>
]]></description><guid isPermaLink="false">112</guid><pubDate>Tue, 30 Jun 2015 05:20:13 +0000</pubDate></item></channel></rss>
