{"id":"l-rf-1-4","courseId":"react-fundamentals","lang":"ar","kind":"lesson","summary":"اقرأ JSX واكتبه من دون صراع مع المترجم، بمعرفة ما يتحوّل إليه، وكيف تعمل الأقواس المعقوصة، وما قواعد الخصائص والعرض التي تختلف عن HTML.","html":"<p>يبدو JSX مثل HTML، فيكون أول ما يخطر لك أن تكتب HTML. وهذا ينجح في أغلب الأحيان. ثم تكتب <code dir=\"ltr\">class=&quot;card&quot;</code> فيظهر تحذير في الـ console، أو تضع <code dir=\"ltr\">if</code> داخل أقواس معقوصة فتحصل على خطأ ترجمة يشير إلى السطر الخطأ. كل واحدة من هذه المفاجآت تصبح منطقية حين ترى حقيقة JSX.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">JSX مجرّد استدعاءات دوال</h2>\n<p>يترجم Vite كل وسم JSX إلى استدعاء دالة. هذا الـ component:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> className</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"title\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Arrival&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>يتحوّل إلى ما يشبه هذا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { jsx } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'react/jsx-runtime'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> jsx</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'h2'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, { className: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'title'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, children: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Arrival'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> });</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>يُرجع الاستدعاء كائن JavaScript عاديًا اسمه <strong>React element</strong>: وصف خفيف لما يجب أن يظهر على الشاشة، له <code dir=\"ltr\">type</code> وبعض الـ <code dir=\"ltr\">props</code>. يمكنك تمثيل الفكرة بدالة صغيرة من عندك:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"2\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> h</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">type</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">props</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#953800;--shiki-dark:#FFA657\">children</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { type, props: { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">props, children } };</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> card</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> h</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'article'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, { className: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'card'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">  h</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'h2'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">null</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Arrival'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">  h</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'p'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">null</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2016</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(card.type);                         </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// article</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(card.props.className);              </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// card</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(card.props.children[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].props.children); </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// [\"Arrival\"]</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p>عناصر React الحقيقية تحمل معلومات أكثر قليلًا، لكن الشكل هو نفسه. تمرّ React على شجرة الكائنات هذه وتُنشئ الـ DOM أو تحدّثه ليطابقها.</p>\n<p>لاحظ أن الكود المترجَم يستورد <code dir=\"ltr\">jsx</code> نيابةً عنك. لهذا لا تبدأ ملفات React الحديثة بالسطر <code dir=\"ltr\">import React from 'react'</code>. الدروس القديمة تتضمّن هذا السطر لأن المترجم السابق كان يحوّل JSX إلى استدعاءات <code dir=\"ltr\">React.createElement(…)</code>، التي تحتاج إلى وجود <code dir=\"ltr\">React</code> في النطاق. ومنذ الـ JSX runtime التلقائي في React 17 لم يعد ضروريًا، فاحذفه.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 200\" role=\"img\" aria-labelledby=\"l-rf-1-4-t1\"><defs><marker id=\"arrow-l-rf-1-4-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-rf-1-4-t1\">يُترجَم مصدر JSX إلى استدعاء للدالة jsx، يُرجع كائنًا عاديًا له type وprops؛ ثم ترسم React هذا الكائن في عقدة DOM حقيقية.</title>\n  <rect class=\"d-box\" x=\"10\" y=\"50\" width=\"190\" height=\"90\" rx=\"12\"/>\n  <text class=\"d-label-muted\" x=\"105\" y=\"40\" text-anchor=\"middle\">ما تكتبه</text>\n  <text class=\"d-code\" x=\"105\" y=\"100\" text-anchor=\"middle\">&lt;h2&gt;Arrival&lt;/h2&gt;</text>\n  <rect class=\"d-box-primary\" x=\"250\" y=\"50\" width=\"200\" height=\"90\" rx=\"12\"/>\n  <text class=\"d-label-muted\" x=\"350\" y=\"40\" text-anchor=\"middle\">ما ينتجه المترجم</text>\n  <text class=\"d-code\" x=\"350\" y=\"88\" text-anchor=\"middle\">{ type: 'h2',</text>\n  <text class=\"d-code\" x=\"350\" y=\"110\" text-anchor=\"middle\">  props: {…} }</text>\n  <rect class=\"d-box-success\" x=\"500\" y=\"50\" width=\"190\" height=\"90\" rx=\"12\"/>\n  <text class=\"d-label-muted\" x=\"595\" y=\"40\" text-anchor=\"middle\">ما تثبّته React</text>\n  <text class=\"d-label-strong\" x=\"595\" y=\"100\" text-anchor=\"middle\">عقدة DOM &lt;h2&gt;</text>\n  <path class=\"d-arrow\" d=\"M200 95 L248 95\" marker-end=\"url(#arrow-l-rf-1-4-1)\"/>\n  <path class=\"d-arrow\" d=\"M450 95 L498 95\" marker-end=\"url(#arrow-l-rf-1-4-1)\"/>\n  <text class=\"d-label-muted\" x=\"350\" y=\"180\" text-anchor=\"middle\">عناصر React أوصاف، لا عُقد DOM</text>\n</svg><figcaption>يتحوّل JSX إلى كائن عنصر، ثم إلى DOM</figcaption></figure>\n<p>حين تعرف أن JSX استدعاءات دوال، تتوقّف القواعد التالية عن الظهور كأنها اعتباطية.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الأقواس المعقوصة تحمل تعبيرات</h2>\n<p>داخل JSX، تعيدك <code dir=\"ltr\">{ }</code> إلى JavaScript. وكل ما تضعه بداخلها يصبح وسيطًا لاستدعاء دالة، لذا يجب أن يكون <strong>تعبيرًا (expression)</strong>: شيئًا ينتج قيمة.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> movie</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { title: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Arrival'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, year: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2016</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, rating: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">8</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> age</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2026</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> movie.year;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.title.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">toUpperCase</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">()</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.year</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> · </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">age</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> years old&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.rating </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 8</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Must watch'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Maybe'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>المتغيّرات والوصول إلى الخصائص واستدعاء الدوال والعمليات الحسابية والمعامل الثلاثي <code dir=\"ltr\">a ? b : c</code> كلها تعبيرات. أمّا <code dir=\"ltr\">if</code> و<code dir=\"ltr\">for</code> و<code dir=\"ltr\">const</code> فجُمل (statements)، فلا يمكن وضعها داخل الأقواس، تمامًا كما لا يمكنك تمرير <code dir=\"ltr\">if (x) {}</code> وسيطًا لدالة. وحين يكبر المنطق، احسب متغيّرًا فوق <code dir=\"ltr\">return</code> واستخدمه.</p>\n<p>هذه هي البطاقة نفسها مع وصف يحتاج إلى تفرّع حقيقي. تعيش جملة <code dir=\"ltr\">if</code> في JavaScript عادية فوق <code dir=\"ltr\">return</code>، ولا يستقبل JSX إلا القيمة النهائية:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">movie</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> label;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (movie.rating </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 9</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    label </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Masterpiece'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">else</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (movie.rating </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 7</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    label </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Must watch'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">else</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    label </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'Maybe'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.title</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">label</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>هذا النمط يتوسّع جيدًا. يبقى الـ JSX صورة مقروءة للمخرجات، وتبقى القرارات في كود عادي يمكنك قراءته واختباره وتتبّع أخطائه كأي دالة أخرى. (الـ <code dir=\"ltr\">{ movie }</code> في قائمة المعاملات prop؛ ستتعلّم الـ props كما يجب في القسم التالي.)</p>\n<p>الخصائص تأخذ أقواسًا معقوصة أيضًا: <code dir=\"ltr\">&lt;img src={movie.poster} alt={movie.title} /&gt;</code>. لا تضع الأقواس داخل علامات اقتباس؛ فـ <code dir=\"ltr\">src=&quot;{poster}&quot;</code> هو النص الحرفي <code dir=\"ltr\">{poster}</code>.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">الخصائص أسماء JavaScript</h2>\n<p>لأن الـ props تصبح مفاتيح في كائن JavaScript، فهي تتبع قواعد التسمية في JavaScript:</p>\n<ul>\n<li><code dir=\"ltr\">class</code> تصبح <code dir=\"ltr\">className</code>، و<code dir=\"ltr\">for</code> تصبح <code dir=\"ltr\">htmlFor</code> (كلتاهما كلمة محجوزة في JS).</li>\n<li>الخصائص المكوّنة من عدّة كلمات تُكتب بصيغة camelCase: <code dir=\"ltr\">onClick</code> و<code dir=\"ltr\">tabIndex</code> و<code dir=\"ltr\">autoComplete</code> و<code dir=\"ltr\">maxLength</code>.</li>\n<li>خصائص <code dir=\"ltr\">aria-*</code> و<code dir=\"ltr\">data-*</code> تحتفظ بالشَّرطات: <code dir=\"ltr\">aria-label=&quot;Remove&quot;</code> و<code dir=\"ltr\">data-id=&quot;42&quot;</code>.</li>\n<li>تأخذ <code dir=\"ltr\">style</code> كائنًا، بخصائص CSS بصيغة camelCase: <code dir=\"ltr\">style={{ marginTop: 8 }}</code>. والرقم المجرّد يعني بكسلات في أغلب الخصائص. والأقواس المزدوجة هي كائن حرفي داخل تعبير JSX.</li>\n</ul>\n<h2 id=\"sec-4\" tabindex=\"-1\">أغلق كل وسم</h2>\n<p>JSX أكثر صرامة من HTML. كل عنصر يجب أن يُغلق: <code dir=\"ltr\">&lt;img /&gt;</code> و<code dir=\"ltr\">&lt;input /&gt;</code> و<code dir=\"ltr\">&lt;br /&gt;</code>. والـ component يُرجع جذرًا واحدًا، ملفوفًا بـ fragment <code dir=\"ltr\">&lt;&gt;…&lt;/&gt;</code> إن احتجت إلى عناصر متجاورة. والتعليقات توضع داخل أقواس معقوصة: <code dir=\"ltr\">{/* like this */}</code>.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">ما الذي يمكن عرضه</h2>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>ما تضعه بين الأقواس</th>\n<th>ما يظهر</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>نص أو رقم</td>\n<td>النص نفسه (بما في ذلك <code dir=\"ltr\">0</code>)</td>\n</tr>\n<tr>\n<td>عنصر React</td>\n<td>ذلك العنصر</td>\n</tr>\n<tr>\n<td>مصفوفة من العناصر</td>\n<td>كل عنصر بالترتيب</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">null</code> و<code dir=\"ltr\">undefined</code> و<code dir=\"ltr\">true</code> و<code dir=\"ltr\">false</code></td>\n<td>لا شيء</td>\n</tr>\n<tr>\n<td>كائن عادي</td>\n<td>خطأ: «Objects are not valid as a React child»</td>\n</tr>\n</tbody>\n</table></div><p>صفّ «لا شيء» هو ما يجعل العرض الشرطي ممكنًا، والـ <code dir=\"ltr\">0</code> في الصف الأول فخّ شهير ستقابله في درس العرض الشرطي.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>عرض كائن كامل</span></p>\n<p>الكود <code dir=\"ltr\">&lt;p&gt;{movie}&lt;/p&gt;</code> يُسقط التطبيق بالخطأ «Objects are not valid as a React child». في الغالب كنت تقصد حقلًا واحدًا: <code dir=\"ltr\">{movie.title}</code>. وإن أردت فحص البيانات أثناء تتبّع خطأ، فاعرض <code dir=\"ltr\">{JSON.stringify(movie)}</code> مؤقتًا.</p>\n</aside>\n<aside class=\"callout callout-why\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/></svg><span><span class=\"callout-kind\">لماذا يهمّ هذا</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>النص يُهرَّب نيابةً عنك</span></p>\n<p>تهرّب React كل نص تعرضه. إذا احتوى عنوان فيلم قادم من API على <code dir=\"ltr\">&lt;script&gt;</code>، فسيظهر كحروف مرئية بدل أن يُنفَّذ. تحصل على حماية من حقن HTML مجانًا، ما دمت لا تتجاوزها باستخدام <code dir=\"ltr\">dangerouslySetInnerHTML</code>.</p>\n</aside>\n<p>صار بإمكانك قراءة أي JSX وتوقّع ما يفعله. في القسم التالي تتوقّف عن كتابة “Arrival” يدويًا، وتتعلّم التفكير بالـ components، فتقسّم شاشة كاملة إلى قطع تستقبل بياناتها عبر الـ props.</p>\n","toc":[{"id":"sec-1","text":"JSX مجرّد استدعاءات دوال","level":2},{"id":"sec-2","text":"الأقواس المعقوصة تحمل تعبيرات","level":2},{"id":"sec-3","text":"الخصائص أسماء JavaScript","level":2},{"id":"sec-4","text":"أغلق كل وسم","level":2},{"id":"sec-5","text":"ما الذي يمكن عرضه","level":2}],"takeaways":["يتحوّل JSX إلى استدعاءات دوال تُنشئ كائنات JavaScript عادية تصف الواجهة، ثم تحوّل React هذه الكائنات إلى DOM.","تضمّ الأقواس المعقوصة أي تعبير JavaScript (قيمة)، لكنها لا تقبل أبدًا جملة مثل <code dir=\"ltr\">if</code> أو <code dir=\"ltr\">for</code>.","الخصائص أسماء JavaScript بصيغة camelCase، لذا تكتب <code dir=\"ltr\">className</code> و<code dir=\"ltr\">htmlFor</code> و<code dir=\"ltr\">onClick</code>، وتمرّر إلى <code dir=\"ltr\">style</code> كائنًا.","النصوص والأرقام تُعرض كنص، بينما <code dir=\"ltr\">null</code> و<code dir=\"ltr\">undefined</code> و<code dir=\"ltr\">true</code> و<code dir=\"ltr\">false</code> لا تعرض شيئًا، والكائنات العادية ترمي خطأ."],"further":[{"title":"Writing Markup with JSX","url":"https://react.dev/learn/writing-markup-with-jsx"},{"title":"JavaScript in JSX with Curly Braces","url":"https://react.dev/learn/javascript-in-jsx-with-curly-braces"},{"title":"Common components (props on every DOM element)","url":"https://react.dev/reference/react-dom/components/common"}],"quiz":[{"q":"<p>إلى ماذا يتحوّل <code dir=\"ltr\">&lt;h2 className=&quot;title&quot;&gt;{movie.title}&lt;/h2&gt;</code> بعد أن يترجمه Vite؟</p>","options":[{"text":"استدعاء دالة يُنشئ كائنًا نوعه <code dir=\"ltr\">'h2'</code> وخصائصه <code dir=\"ltr\">{ className: 'title', children: movie.title }</code>.","why":"صحيح. JSX صياغة لإنشاء كائنات عناصر، وReact تقرأ هذه الكائنات لتقرّر أي DOM تُنشئ أو تحدّث."},{"text":"نص HTML تُدرجه React باستخدام innerHTML.","why":"لا تبني React نصوص HTML أبدًا من أجل الرسم. ولهذا أيضًا يكون النص في JSX آمنًا افتراضيًا من حقن HTML."},{"text":"عنصر <code dir=\"ltr\">HTMLHeadingElement</code> حقيقي يُنشأ باستخدام <code dir=\"ltr\">document.createElement</code>.","why":"JSX لا ينتج إلا كائنات وصف خفيفة. تُنشئ React عُقد الـ DOM أو تعيد استخدامها لاحقًا، في مرحلة الـ commit."},{"text":"يبقى JSX كما هو ويفهمه المتصفّح مباشرة.","why":"المتصفّحات لا تفهم JSX. من دون خطوة ترجمة ترمي الصفحة خطأً في الصياغة."}],"answer":0},{"q":"<p>أيّ سطر هو JSX صحيح؟</p>","options":[{"text":"<code dir=\"ltr\">&lt;p&gt;{if (watched) 'Seen'}&lt;/p&gt;</code>","why":"<code dir=\"ltr\">if</code> جملة وليست تعبيرًا، فلا يمكن وضعها داخل الأقواس المعقوصة. استخدم المعامل الثلاثي أو احسب القيمة قبل <code dir=\"ltr\">return</code>."},{"text":"<code dir=\"ltr\">&lt;img src=&quot;{poster}&quot;&gt;</code>","why":"علامات الاقتباس تجعلها النص الحرفي “{poster}”، والوسم غير مغلق. اكتب <code dir=\"ltr\">src={poster}</code> وأغلق الوسم ذاتيًا بـ <code dir=\"ltr\">/&gt;</code>."},{"text":"<code dir=\"ltr\">&lt;label class=&quot;field&quot; for=&quot;title&quot;&gt;Title&lt;/label&gt;</code>","why":"في JSX تُكتب هاتان الخاصيتان <code dir=\"ltr\">className</code> و<code dir=\"ltr\">htmlFor</code>، لأن <code dir=\"ltr\">class</code> و<code dir=\"ltr\">for</code> كلمتان محجوزتان في JavaScript."},{"text":"<code dir=\"ltr\">&lt;div style={{ marginTop: 8, fontWeight: 'bold' }}&gt;Hi&lt;/div&gt;</code>","why":"صحيح. الأقواس الخارجية تُدخلك إلى JavaScript، والداخلية كائن، وخصائص CSS بصيغة camelCase. والرقم المجرّد يعني بكسلات."}],"answer":3},{"q":"<p>قيمة <code dir=\"ltr\">movie</code> هي <code dir=\"ltr\">{ title: 'Arrival', year: 2016 }</code>. ماذا يحدث مع <code dir=\"ltr\">&lt;p&gt;{movie}&lt;/p&gt;</code>؟</p>","options":[{"text":"يُعرض النص “[object Object]”.","why":"لا تستدعي React الدالة toString على الكائنات، بل ترفض عرضها أصلًا."},{"text":"ترمي React الخطأ «Objects are not valid as a React child».","why":"صحيح. تستطيع React عرض النصوص والأرقام والعناصر ومصفوفات منها. اعرض حقلًا واحدًا بدلًا من ذلك، مثل <code dir=\"ltr\">{movie.title}</code>."},{"text":"يُعرض الكائن بصيغة JSON.","why":"لا تحوّل React الكائنات إلى نص نيابةً عنك. استخدم <code dir=\"ltr\">JSON.stringify(movie)</code> إن كنت تريد فعلًا عرض JSON."},{"text":"لا يُعرض شيء، تمامًا مثل <code dir=\"ltr\">null</code>.","why":"وحدها <code dir=\"ltr\">null</code> و<code dir=\"ltr\">undefined</code> والقيم المنطقية لا تعرض شيئًا. أمّا الكائن العادي فخطأ."}],"answer":1},{"q":"<p>يحتوي وصف أحد الأفلام القادم من الـ API على <code dir=\"ltr\">&lt;b&gt;Must watch&lt;/b&gt;</code>. تعرضه بالشكل <code dir=\"ltr\">&lt;p&gt;{movie.description}&lt;/p&gt;</code>. ماذا يظهر؟</p>","options":[{"text":"عبارة “Must watch” بخط عريض.","why":"لا تفسّر React النصوص على أنها HTML، وهذا يحميك من الـ markup المحقون."},{"text":"خطأ، لأن النص يحتوي على أقواس زاوية.","why":"أي نص محتوى صالح. تهرّب React رموزه وتعرضه كنص."},{"text":"النص الحرفي <code dir=\"ltr\">&lt;b&gt;Must watch&lt;/b&gt;</code> بوسومه كاملة.","why":"صحيح. تهرّب React محتوى النصوص، فيظهر الـ markup الموجود في البيانات كحروف بدل أن يُنفَّذ. وهذا خط دفاع أساسي ضد هجمات cross-site scripting."}],"answer":2}],"exercise":{"kind":"web","mode":"js","starter":{"js":"// A tiny stand-in for what JSX compiles to.\nfunction h(type, props, ...children) {\n  return { type, props: { ...props, children } };\n}\n\n// Write the h() calls this JSX compiles to:\n//\n// <article className=\"card\">\n//   <h2>{movie.title}</h2>\n//   <p>{movie.year}</p>\n// </article>\nfunction buildCard(movie) {\n  return h('article', null);\n}\n"},"solution":{"js":"// A tiny stand-in for what JSX compiles to.\nfunction h(type, props, ...children) {\n  return { type, props: { ...props, children } };\n}\n\n// Write the h() calls this JSX compiles to:\n//\n// <article className=\"card\">\n//   <h2>{movie.title}</h2>\n//   <p>{movie.year}</p>\n// </article>\nfunction buildCard(movie) {\n  return h('article', { className: 'card' },\n    h('h2', null, movie.title),\n    h('p', null, movie.year),\n  );\n}\n"},"checks":[{"id":"root","test":"const el = buildCard({ title: 'Arrival', year: 2016 }); return el.type === 'article' && el.props.className === 'card';"},{"id":"two-children","test":"const el = buildCard({ title: 'Arrival', year: 2016 }); const c = el.props.children; return Array.isArray(c) && c.length === 2 && c[0].type === 'h2' && c[1].type === 'p';"},{"id":"title-text","test":"const el = buildCard({ title: 'Arrival', year: 2016 }); return [].concat(el.props.children[0].props.children).join('') === 'Arrival';"},{"id":"uses-data","test":"const el = buildCard({ title: 'Past Lives', year: 2023 }); const [t, y] = el.props.children; return [].concat(t.props.children).join('') === 'Past Lives' && [].concat(y.props.children).join('') === '2023';"}],"title":"ترجم JSX بيدك","prompt":"<p>JSX مجرّد استدعاءات دوال. يعطيك كود البداية الدالة <code dir=\"ltr\">h(type, props, ...children)</code>، وهي نسخة مبسّطة مما ينتجه المترجم. أكمل <code dir=\"ltr\">buildCard(movie)</code> لتُرجع بالضبط ما سينشئه هذا الـ JSX:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> className</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"card\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.title</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.year</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span></code></pre></div>\n<p>استخدم الوسيط <code dir=\"ltr\">movie</code>، لا قيمًا مكتوبة يدويًا.</p>\n","hints":["الوسيط الأول اسم الوسم كنص، والثاني كائن الخصائص (أو <code dir=\"ltr\">null</code>)، وكل وسيط بعد ذلك ابن (child).","الخصائص توضع في كائن الـ props: <code dir=\"ltr\">{ className: 'card' }</code>.","يمكن أن يكون الأبناء استدعاءات <code dir=\"ltr\">h()</code> أخرى: <code dir=\"ltr\">h('article', { className: 'card' }, h('h2', null, movie.title), …)</code>."],"explanation":"<p>كل وسم JSX يصبح استدعاءً واحدًا: اسم الوسم، ثم كائن الخصائص، ثم الأبناء بالترتيب. والتعبيرات داخل الأقواس المعقوصة مثل <code dir=\"ltr\">{movie.title}</code> مجرّد وسائط، ولهذا لا يُسمح بداخلها إلا بالتعبيرات. تختلف الدالة <code dir=\"ltr\">jsx()</code> الحقيقية في React في التفاصيل (فهي تستقبل الأبناء داخل كائن الـ props مباشرة بدل أن تأخذهم وسائط إضافية، ولا تضع الابن الوحيد داخل مصفوفة، وتستقبل الـ key منفصلًا)، لكن شجرة الكائنات العادية هي الفكرة نفسها.</p>\n","checkLabels":{"root":"الجذر “article” وقيمة className فيه “card”","two-children":"له ابنان: “h2” ثم “p”","title-text":"يحتوي الـ h2 على عنوان الفيلم","uses-data":"يعمل مع أي فيلم، لا مع Arrival فقط"}},"words":654,"readMinutes":4}