{"id":"l-rn-1-1","courseId":"react-native-apps","lang":"ar","kind":"intro","summary":"اشرح كيف يحوّل تطبيق React Native الـ components التي تكتبها إلى views حقيقية على iOS وAndroid، وما الذي غيّرته الـ New Architecture في هذا المسار.","html":"<p>افتح تطبيق Notes على هاتفك واسحب إصبعك نزولًا على قائمة طويلة. الارتداد عند أعلى القائمة، وطريقة ظهور مقابض تحديد النص، والتمرير الذي يواصل الانزلاق بعد أن ترفع إصبعك: كل ذلك من كود نظام التشغيل نفسه. ووعد React Native أن يحصل تطبيقك على السلوك نفسه، لأنه يستخدم الـ views نفسها.</p>\n<p>نبني في هذه الدورة <strong>Trailhead</strong>، وهو سجلّ لرحلات المشي. في النهاية سيكون لديك قائمة بالرحلات السابقة، وشاشات لتفاصيل كل درب، ونموذج لتسجيل رحلة جديدة، وتتبّع بالـ GPS، وصور، وتذكيرات، وتخزين دون اتصال، وbuild يعمل على هاتف حقيقي. وكل درس يضيف قطعة واحدة.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">عناصر أصلية تصفها React</h2>\n<p>على الويب، تحوّل React الـ components إلى عُقد DOM، ثم يرسمها المتصفّح. أما React Native فيستبدل الطبقة السفلى. أنت تكتب components باستخدام <code dir=\"ltr\">&lt;View&gt;</code> و<code dir=\"ltr\">&lt;Text&gt;</code> و<code dir=\"ltr\">&lt;Image&gt;</code>؛ وتحسب React ما الذي تغيّر؛ ثم يُنشئ مُصيِّر React Native الـ <strong>native views</strong> (عناصر الواجهة الأصلية للمنصّة) أو يحدّثها: <code dir=\"ltr\">UIView</code> على iOS، و<code dir=\"ltr\">android.view.View</code> على Android.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">src/app/index.tsx</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\"> { Text, View } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'react-native'</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\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> Home</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </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\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">View</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> style</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ flex: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, justifyContent: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'center'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, alignItems: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'center'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</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\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Trailhead&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</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\">View</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>لا HTML، ولا ملف CSS، ولا DOM. كائن <code dir=\"ltr\">style</code> يشبه CSS، وهذا مقصود، لكنه كائن JavaScript يقرؤه محرّك التخطيط في React Native (واسمه Yoga) ليحدّد أماكن الـ native views.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 250\" role=\"img\" aria-labelledby=\"l-rn-1-1-t1\"><defs><marker id=\"arrow-l-rn-1-1-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-rn-1-1-t1\">الـ components تعمل في Hermes على الـ JS thread؛ تحسب React التغييرات؛ ويستخدم مُصيِّر Fabric واجهة JSI لإنشاء native views يرسمها الـ UI thread على iOS وAndroid.</title>\n  <rect class=\"d-box-primary\" x=\"20\" y=\"30\" width=\"190\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"115\" y=\"62\" text-anchor=\"middle\">الـ components</text>\n  <text class=\"d-label-muted\" x=\"115\" y=\"88\" text-anchor=\"middle\">JS thread · Hermes</text>\n  <path class=\"d-arrow\" d=\"M210 70 L270 70\" marker-end=\"url(#arrow-l-rn-1-1-1)\"/>\n  <rect class=\"d-box-accent\" x=\"275\" y=\"30\" width=\"170\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"360\" y=\"62\" text-anchor=\"middle\">مُصيِّر Fabric</text>\n  <text class=\"d-label-muted\" x=\"360\" y=\"88\" text-anchor=\"middle\">C++ عبر JSI</text>\n  <path class=\"d-arrow\" d=\"M445 70 L505 70\" marker-end=\"url(#arrow-l-rn-1-1-1)\"/>\n  <rect class=\"d-box-success\" x=\"510\" y=\"30\" width=\"150\" height=\"80\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"585\" y=\"62\" text-anchor=\"middle\">Native views</text>\n  <text class=\"d-label-muted\" x=\"585\" y=\"88\" text-anchor=\"middle\">UI thread</text>\n  <rect class=\"d-box\" x=\"450\" y=\"160\" width=\"100\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"500\" y=\"190\" text-anchor=\"middle\">iOS</text>\n  <rect class=\"d-box\" x=\"570\" y=\"160\" width=\"100\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"620\" y=\"190\" text-anchor=\"middle\">Android</text>\n  <path class=\"d-line\" d=\"M585 110 L500 160\"/>\n  <path class=\"d-line\" d=\"M585 110 L620 160\"/>\n  <text class=\"d-label-muted\" x=\"115\" y=\"150\" text-anchor=\"middle\">أحداث اللمس تعود</text>\n  <path class=\"d-arrow d-dashed\" d=\"M510 100 L210 135\" marker-end=\"url(#arrow-l-rn-1-1-1)\"/>\n</svg><figcaption>من الـ component إلى البكسلات</figcaption></figure>\n<h2 id=\"sec-2\" tabindex=\"-1\">خيطان (threads) يهمّانك</h2>\n<p>يعمل كود JavaScript في <strong>Hermes</strong>، وهو محرّك JavaScript صُمّم لـ React Native، على thread خاص به. أما <strong>الـ UI thread</strong> الخاص بالمنصّة فيرسم الـ views ويستقبل اللمسات. وفصلهما هو ما يجعل التمرير الأصلي سلسًا بينما يعمل كودك، وهو أيضًا ما يجعل الأزرار تبدو ميتة عندما تشغّل حلقة تكرار متزامنة طويلة في JavaScript: اللمسة تصل، لكن لا أحد متفرّغ لمعالجتها.</p>\n<p>ستعود إلى هذا في درس الأداء. أما الآن فتذكّر القاعدة العملية: أبقِ الـ JS thread متفرّغًا أثناء الإيماءات والحركات.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">الـ New Architecture باختصار</h2>\n<p>لسنوات، كانت JavaScript والكود الأصلي يتواصلان عبر «جسر» (bridge) يحوّل الرسائل إلى JSON ويرسلها على دفعات. ثم حلّت محلّه <strong>الـ New Architecture</strong> (المعمارية الجديدة):</p>\n<ul>\n<li><strong>JSI</strong> تتيح لـ JavaScript استدعاء C++ مباشرة والاحتفاظ بمراجع لكائنات أصلية.</li>\n<li><strong>Fabric</strong> هو المُصيِّر (renderer) الجديد، مكتوب بـ C++ ومشترك بين المنصّتين.</li>\n<li><strong>الـ TurboModules</strong> وحدات أصلية (الكاميرا، التخزين، المستشعرات) تُحمَّل عند الحاجة، أي عند أول استخدام.</li>\n</ul>\n<p>أصبحت المعمارية الافتراضية في React Native 0.76، والخيار الوحيد بدءًا من 0.82. لن تضبط أيًّا منها بنفسك؛ فمشاريع Expo تستخدمها مباشرة. لكنها تهمّ عند اختيار المكتبات: أي مكتبة تثبّتها يجب أن تدعمها، والمكتبات التي تخضع للصيانة تدعمها.</p>\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>حين تقرأ مقالًا من 2021 يتحدّث عن «الـ bridge» أو «حركة المرور عبر الـ bridge»، فهو يصف معمارية لم تعد في تطبيقك. تحقّق من التاريخ قبل أن تنسخ نصيحة عن الأداء.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">ما الذي ينتقل من React وما الذي لا ينتقل</h2>\n<p>الـ components والـ props والـ state والـ hooks والـ context والـ keys: كلها كما هي. وميزات React 19 تعمل أيضًا. ما يتغيّر هو كل ما يحيط بـ React: العناصر الأساسية (<code dir=\"ltr\">View</code> بدلًا من <code dir=\"ltr\">div</code>)، والتنسيق (لا cascade، وflexbox يبدأ بالاتجاه العمودي)، والتنقّل (stacks وtabs بدلًا من عناوين URL في شريط)، وواجهات الجهاز (أذونات قد يرفضها المستخدم)، والإطلاق (مراجعة المتجر بدلًا من deploy).</p>\n<p>في الدرس التالي ستنشئ مشروع Trailhead باستخدام Expo وتشغّله على هاتفك.</p>\n","toc":[{"id":"sec-1","text":"عناصر أصلية تصفها React","level":2},{"id":"sec-2","text":"خيطان (threads) يهمّانك","level":2},{"id":"sec-3","text":"الـ New Architecture باختصار","level":2},{"id":"sec-4","text":"ما الذي ينتقل من React وما الذي لا ينتقل","level":2}],"takeaways":["يرسم React Native عناصر واجهة أصلية حقيقية مثل UIView على iOS وandroid.view.View على Android؛ فلا متصفّح ولا DOM.","يعمل كود JavaScript في محرّك Hermes على thread خاص به، بينما يرسم الـ UI thread الخاص بالمنصّة البكسلات ويستقبل اللمسات.","الـ New Architecture (أي JSI ومُصيِّر Fabric والـ TurboModules) هي المعمارية الوحيدة منذ React Native 0.82.","معرفتك بـ React تنتقل كما هي؛ والذي يتغيّر هو مجموعة العناصر الأساسية والتنسيق والتنقّل وطريقة الإطلاق."],"further":[{"title":"Core Components and Native Components","url":"https://reactnative.dev/docs/intro-react-native-components"},{"title":"About the New Architecture","url":"https://reactnative.dev/architecture/landing-page"}],"quiz":[{"q":"<p>يقول زميلك إن «React Native مجرد WebView بواجهة برمجية أجمل». ما التصحيح الأدق؟</p>","options":[{"text":"إنه يرسم HTML، لكنه يحوّله إلى كود أصلي مسبقًا قبل التشغيل.","why":"لا يوجد HTML في أي مرحلة. أنت تكتب components من React مثل <code dir=\"ltr\">&lt;View&gt;</code> و<code dir=\"ltr\">&lt;Text&gt;</code>، ولا تكتب <code dir=\"ltr\">&lt;div&gt;</code> أبدًا."},{"text":"الـ components التي تكتبها تصبح views حقيقية من المنصّة؛ JavaScript تصف الواجهة والكود الأصلي يرسمها.","why":"صحيح. مُصيِّر React Native ينشئ الـ native views ويحدّثها، ولهذا يبدو التمرير وإدخال النص كما في أي تطبيق آخر."},{"text":"يستخدم WebView على Android وviews أصلية على iOS.","why":"المنصّتان تحصلان على views أصلية. Android ليس هدفًا من الدرجة الثانية يعتمد على متصفّح كحلّ احتياطي."}],"answer":1},{"q":"<p>يشغّل Trailhead حلقة تكرار ثقيلة في JavaScript لمدة ثانيتين. ما الذي سيلاحظه المستخدم على الأرجح؟</p>","options":[{"text":"لا شيء، لأن JavaScript تعمل على الـ UI thread ولها الأولوية.","why":"JavaScript لا تعمل على الـ UI thread. وهذا الفصل بالذات هو ما يجعلها قادرة على التأخّر دون أن يلاحظ نظام التشغيل."},{"text":"ينهار التطبيق فورًا بخطأ نفاد الذاكرة.","why":"الحلقة الطويلة تحجب التنفيذ، ولا تحجز ذاكرة بلا حدود. سترى تجمّدًا، لا انهيارًا."},{"text":"تتوقّف الاستجابة للمسات والتحديثات التي تقودها JavaScript حتى تنتهي الحلقة، مع أن نظام التشغيل يُبقي التطبيق حيًّا.","why":"صحيح. الـ JS thread مشغول، فلا يستطيع الاستجابة للأحداث أو جدولة عمليات render. أما العمل الذي يقوده الكود الأصلي، مثل التمرير الذاتي لـ ScrollView، فقد يستمر."}],"answer":2},{"q":"<p>ما الذي يمنحك إياه JSI، وهو جزء من الـ New Architecture؟</p>","options":[{"text":"استدعاءات مباشرة بين JavaScript وC++ دون تحويل كل رسالة إلى JSON.","why":"صحيح. كان الـ bridge القديم يجمع رسائل JSON ويرسلها بشكل غير متزامن؛ أما JSI فيتيح لـ JavaScript الاحتفاظ بمراجع لكائنات أصلية واستدعاءها مباشرة."},{"text":"طريقة لكتابة الواجهة بـ Swift وKotlin بدلًا من JSX.","why":"ما زلت تكتب الواجهة بـ React. JSI طبقة توصيل تحت السطح، ونادرًا ما تتعامل معها بنفسك."},{"text":"محرّك JavaScript يحلّ محلّ Hermes.","why":"ما زال Hermes هو المحرّك. JSI هي الواجهة التي تكشفها المحرّكات للكود الأصلي، وليست محرّكًا."}],"answer":0}],"exercise":{"kind":"choice","multiple":true,"options":["native-views","js-thread","css-file","bridge-json","react-skills"],"correct":["native-views","js-thread","react-skills"],"title":"ما الذي يحدث فعلًا على الهاتف؟","prompt":"<p>تعرض الشاشة الأولى في Trailhead قائمة بالرحلات وزرًّا كبيرًا مكتوبًا عليه <strong>Log a hike</strong>. اختر <strong>كل</strong> عبارة صحيحة عن طريقة عمل هذه الشاشة على الهاتف اليوم.</p>\n","hints":["فكّر في من يرسم البكسلات، وأين يعمل كودك.","تذكّر المعمارية التي يستخدمها React Native حصرًا منذ الإصدار 0.82.","ثلاث عبارات صحيحة."],"explanation":"<p>القائمة والزر native views حقيقية ينشئها مُصيِّر Fabric، وكود JavaScript يعمل في Hermes على thread خاص به، منفصل عن الـ UI thread الذي يرسم ويستقبل اللمسات. ومعرفتك بـ React تنتقل دون تغيير. لا يوجد ملف CSS ولا cascade: التنسيقات كائنات JavaScript. أما الـ bridge الذي يجمع رسائل JSON فهو من المعمارية القديمة، وقد حلّت JSI محلّه.</p>\n","checkLabels":{},"optionText":{"native-views":{"text":"الزر view حقيقي من المنصّة، من النوع نفسه الذي يستخدمه تطبيق مكتوب بـ Swift أو Kotlin.","why":"صحيحة. مُصيِّر React Native ينشئ native views، لا عناصر HTML داخل WebView."},"js-thread":{"text":"إذا كان الـ JS thread مشغولًا بحلقة تكرار طويلة، يتوقّف الزر عن الاستجابة للمسات حتى تنتهي.","why":"صحيحة. اللمسة تصل إلى الـ UI thread، لكن معالج JavaScript لا يستطيع العمل حتى يتفرّغ الـ JS thread."},"css-file":{"text":"ألوان الزر تأتي من ملف CSS تنتقل قواعده بالتتابع (cascade) إلى الـ components الأبناء.","why":"خاطئة. التنسيقات كائنات JavaScript عادية تُمرَّر لكل component؛ ولا يوجد cascade من ملف تنسيق."},"bridge-json":{"text":"كل ضغطة على الزر تُحوَّل إلى JSON وتُرسَل عبر الـ bridge ضمن دفعة.","why":"خاطئة. هذا وصف للمعمارية القديمة. مع الـ New Architecture تتيح JSI لـ JavaScript والكود الأصلي أن يستدعي كلٌّ منهما الآخر مباشرة."},"react-skills":{"text":"تستخدم الشاشة الـ components والـ props والـ state والـ hooks نفسها التي تعرفها من React.","why":"صحيحة. React نفسها لم تتغيّر؛ ما يتغيّر هو العناصر الأساسية والمنصّة من حولها."}}},"words":485,"readMinutes":3}