{"id":"l-rn-1-3","courseId":"react-native-apps","lang":"ar","kind":"lesson","summary":"ابنِ شاشة تفاصيل الرحلة في Trailhead باستخدام View وText وImage وScrollView، وتجنّب قواعد النص والصور التي تُسقط شاشات الجوّال أو تتركها فارغة.","html":"<p>على الويب، يمكنك أن ترمي نصًّا داخل <code dir=\"ltr\">div</code>، وتضبط الخط على <code dir=\"ltr\">body</code>، وتضع <code dir=\"ltr\">&lt;img&gt;</code> دون أن تفكّر في حجمها. جرّب الشيء نفسه في React Native وستحصل على شاشة خطأ حمراء، أو نص بخط خاطئ، أو صورة لا تظهر أبدًا. أربعة components تحمل معظم الشاشات، ولكلٍّ منها قاعدة واحدة تُوقع مطوّري الويب.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">View: صندوق، لا أكثر</h2>\n<p><code dir=\"ltr\">View</code> هو حجر البناء في التخطيط: مستطيل يمكن أن يكون له خلفية وحدود وحشو (padding) وأبناء. ويقابله view حاوية أصلي. ليس فيه عقدة نصية، لذا <strong>لا يمكن أن يحوي نصوصًا</strong>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">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:#6E7781;--shiki-dark:#8B949E\">// Throws: Text strings must be rendered within a &#x3C;Text> component.</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\">>Ridge Loop&#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>\n<span class=\"line\"><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// Works</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\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Ridge Loop&#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></code></pre></div>\n<p>فكّر في <code dir=\"ltr\">View</code> على أنه الـ <code dir=\"ltr\">div</code> الذي تستخدمه للتخطيط، مطروحًا منه كل ما يفعله الـ <code dir=\"ltr\">div</code> مع النص. وهو أيضًا أكثر ما ستنسّقه: البطاقات والصفوف والفواصل والشارات والمسافات الفارغة كلها Views لها خلفية أو حواف مستديرة أو بعض الحشو. الـ Views رخيصة لكنها ليست مجانية؛ فكل واحد منها يصبح native view حقيقيًا، وصفّ في قائمة فيه اثنتا عشرة طبقة تغليف متداخلة يكلّف أكثر من صفّ فيه أربع. قلّل الطبقات حين لا تضيف الطبقة شيئًا.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Text: المكان الوحيد للنصوص</h2>\n<p>كل نص مرئي يوضع داخل <code dir=\"ltr\">&lt;Text&gt;</code>. عناصر <code dir=\"ltr\">&lt;Text&gt;</code> المتداخلة تصبح فقرة واحدة، وهذا أيضًا <strong>المكان الوحيد</strong> الذي توجد فيه وراثة التنسيق: الـ <code dir=\"ltr\">Text</code> الابن يرث الخط واللون والحجم من <code dir=\"ltr\">Text</code> الأب.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">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:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</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\">{ fontSize: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">16</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, color: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#333'</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\">  Ridge Loop is &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</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\">{ fontWeight: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'700'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>8.4 km&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">> with 420 m of climbing.</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\">></span></span></code></pre></div>\n<p>الـ <code dir=\"ltr\">View</code> لا يمرّر تنسيقات النص إلى أسفل أبدًا. وإن أردت خطًّا موحّدًا في التطبيق كله، فاصنع component (مثل <code dir=\"ltr\">AppText</code> يضبط القيم الافتراضية التي تريدها) بدلًا من البحث عن ملف تنسيق عام غير موجود.</p>\n<p>والنص أيضًا يتكيّف مع إعدادات إمكانية الوصول (accessibility) لدى المستخدم. من ضبط حجم خط أكبر في إعدادات iOS أو Android يحصل على نص أكبر في تطبيقك تلقائيًا، وهذا جيد، لكنه يعني أن أي صندوق بارتفاع ثابت حول النص سيقصّه في النهاية. اترك مجالًا للنمو، وفضّل الحشو على الارتفاعات الثابتة في أي شيء يحوي كلمات.</p>\n<p>وستستخدم اثنين من الـ props باستمرار: <code dir=\"ltr\">numberOfLines={2}</code> يقتطع النص ويضيف علامة حذف (مثالي لبطاقات القوائم)، و<code dir=\"ltr\">selectable</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>الـ <code dir=\"ltr\">&amp;&amp;</code> الذي يرسم صفرًا</span></p>\n<p><code dir=\"ltr\">{hike.photoCount &amp;&amp; &lt;Text&gt;{hike.photoCount} photos&lt;/Text&gt;}</code> يعمل على الويب، حيث يظهر الـ <code dir=\"ltr\">0</code> الشارد كحرف غير مؤذٍ. أما في React Native فـ <code dir=\"ltr\">0 &amp;&amp; …</code> تُقيَّم إلى <code dir=\"ltr\">0</code>، فتحاول React رسم هذا الرقم مباشرة داخل <code dir=\"ltr\">View</code>، فيرمي التطبيق خطأ. اكتب قيمة منطقية حقيقية: <code dir=\"ltr\">{hike.photoCount &gt; 0 &amp;&amp; …}</code>.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">Image: أخبره بحجمه</h2>\n<p>للصور المضمّنة في التطبيق، يحلّ <code dir=\"ltr\">require()</code> الملف وقت البناء، فيعرف React Native أبعاد الصورة:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">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:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Image</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> source</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">require</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'../../assets/images/trail-placeholder.png'</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></code></pre></div>\n<p>أما صور الشبكة، فلا يستطيع React Native معرفة حجمها حتى ينتهي التنزيل، لذا يجب أن تعطيه حجمًا. دون ذلك تُرسم الصورة بحجم 0 في 0، بصمت.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">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:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Image</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  source</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ uri: hike.photoUrl }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  style</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ width: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'100%'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, height: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">220</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, borderRadius: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">12</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  resizeMode</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"cover\"</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  accessibilityLabel</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">`Photo from ${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">.</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">name</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}`</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">/></span></span></code></pre></div>\n<p>تعمل <code dir=\"ltr\">resizeMode</code> مثل <code dir=\"ltr\">object-fit</code> في CSS: <code dir=\"ltr\">cover</code> تملأ وتقصّ، و<code dir=\"ltr\">contain</code> تحتوي الصورة كاملة. وفي تطبيقات الإنتاج تستخدم فرق كثيرة <code dir=\"ltr\">expo-image</code> بدلًا منه: له الشكل الأساسي نفسه، ويضيف التخزين المؤقت على القرص والصور المؤقتة (placeholders)، ويستخدم <code dir=\"ltr\">contentFit</code> بدلًا من <code dir=\"ltr\">resizeMode</code>.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">ScrollView: محتوى قد لا يتّسع</h2>\n<p>الـ native views لا تتمرّر عند تجاوز المحتوى لحدودها. التمرير component مستقل اسمه <code dir=\"ltr\">ScrollView</code>، وله خاصّيتان غريبتان.</p>\n<p>أولًا، يحتاج إلى <strong>ارتفاع محدود</strong>: فهو يتمرّر داخل المساحة التي يمنحه إياها الأب، لذا تحتاج سلسلة الآباء إلى <code dir=\"ltr\">flex: 1</code> (سترى السبب في درس الـ flexbox). ثانيًا، الحشو والمحاذاة للمحتوى المتمرّر توضع في <code dir=\"ltr\">contentContainerStyle</code>، لا في <code dir=\"ltr\">style</code>. فـ <code dir=\"ltr\">style</code> يحدّد حجم نافذة التمرير، و<code dir=\"ltr\">contentContainerStyle</code> ينسّق المحتوى الذي ينزلق داخلها.</p>\n<p>هذه شاشة التفاصيل في Trailhead، مع بيانات تجريبية حاليًا:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">src/app/hike.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\"> { Image, ScrollView, 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\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> hike</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\">  name: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Ridge Loop'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  photoUrl: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'https://images.example.com/ridge-loop.jpg'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  distanceKm: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">8.4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  elevationM: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">420</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  notes: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Steep first kilometre, then a long ridge with views of the lake. Bring water: the spring at the saddle was dry.'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  photoCount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</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\">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\"> HikeScreen</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\">ScrollView</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\"> }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> contentContainerStyle</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ padding: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">16</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, gap: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">12</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\">Image</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">        source</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ uri: hike.photoUrl }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">        style</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ width: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'100%'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, height: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">220</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, borderRadius: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">12</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">        accessibilityLabel</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">`Photo from ${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">.</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">name</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}`</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</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\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</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\">{ fontSize: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">28</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, fontWeight: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'700'</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 style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.name</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\">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:#0550AE;--shiki-dark:#79C0FF\"> style</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ flexDirection: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'row'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, gap: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">16</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\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.distanceKm</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> km&#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\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.elevationM</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> m up&#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:#CF222E;--shiki-dark:#FF7B72\">      {</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.photoCount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x26;&#x26;</span><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\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.photoCount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> photos&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</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:#0550AE;--shiki-dark:#79C0FF\"> style</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{ fontSize: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">16</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, lineHeight: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">24</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 style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.notes</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\">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\">ScrollView</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\">div</code>، ولا أسماء classes، ولا استيراد لملف تنسيق، ولا نصوص شاردة. والأرقام مثل <code dir=\"ltr\">hike.distanceKm</code> موجودة داخل <code dir=\"ltr\">Text</code>، فتُرسم دون مشكلة.</p>\n<aside class=\"callout callout-note\" 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\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">ملاحظة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>وماذا عن قائمة من 300 رحلة؟</span></p>\n<p>يرسم <code dir=\"ltr\">ScrollView</code> كل ابن فورًا، حتى البعيد عن الشاشة. لشاشة محتوى هذا جيد. أما لقائمة بيانات تكبر، فمعناه بدء تشغيل بطيء واستهلاك عالٍ للذاكرة. ستستخدم <code dir=\"ltr\">FlatList</code> لذلك في القسم 2.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">بقية المجموعة الأساسية</h2>\n<p>ستتعرّف على البقية حين يحتاج إليها Trailhead: <code dir=\"ltr\">Pressable</code> و<code dir=\"ltr\">TextInput</code> في الدرس التالي، و<code dir=\"ltr\">FlatList</code> و<code dir=\"ltr\">SectionList</code> للقوائم، و<code dir=\"ltr\">ActivityIndicator</code> للتحميل، و<code dir=\"ltr\">Switch</code> لمفاتيح التبديل، و<code dir=\"ltr\">Modal</code> للطبقات العائمة، و<code dir=\"ltr\">KeyboardAvoidingView</code> للنماذج. كلٌّ منها يقابله component أصلي، فتبدو وتتصرّف كما تتصرّف عناصر المنصّة افتراضيًا.</p>\n<p>في الدرس التالي ستجعل Trailhead تفاعليًا: أزرار تستجيب للمس، وحقول إدخال تتعامل مع الكتابة.</p>\n","toc":[{"id":"sec-1","text":"View: صندوق، لا أكثر","level":2},{"id":"sec-2","text":"Text: المكان الوحيد للنصوص","level":2},{"id":"sec-3","text":"Image: أخبره بحجمه","level":2},{"id":"sec-4","text":"ScrollView: محتوى قد لا يتّسع","level":2},{"id":"sec-5","text":"بقية المجموعة الأساسية","level":2}],"takeaways":["<code dir=\"ltr\">View</code> صندوق للتخطيط ولا يمكن أن يحوي نصًّا خامًا؛ كل نصّ يجب أن يكون داخل <code dir=\"ltr\">&lt;Text&gt;</code>.","تنسيقات النص تُورَث فقط من <code dir=\"ltr\">&lt;Text&gt;</code> أب، ولا تُورَث أبدًا من <code dir=\"ltr\">&lt;View&gt;</code>.","صور الشبكة تحتاج إلى عرض وارتفاع صريحين؛ أما الصور المحلية المحمّلة عبر <code dir=\"ltr\">require()</code> فتعرف حجمها بنفسها.","<code dir=\"ltr\">ScrollView</code> يرسم كل أبنائه دفعة واحدة ويحتاج إلى ارتفاع محدود، فاستخدمه لشاشات المحتوى، لا لقوائم البيانات الطويلة.","<code dir=\"ltr\">{count &amp;&amp; &lt;Text&gt;…&lt;/Text&gt;}</code> ينهار حين تكون <code dir=\"ltr\">count</code> صفرًا، لأن 0 يُرسم كنصّ خام؛ استخدم مقارنة صريحة بدلًا من ذلك."],"further":[{"title":"Core Components and APIs","url":"https://reactnative.dev/docs/components-and-apis"},{"title":"Text","url":"https://reactnative.dev/docs/text"},{"title":"Image","url":"https://reactnative.dev/docs/image"}],"quiz":[{"q":"<p>أيّ سطر يرمي الخطأ “Text strings must be rendered within a <Text> component”؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"tsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">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:#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\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Ridge Loop&#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:#CF222E;--shiki-dark:#FF7B72\">  {</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.photoCount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x26;&#x26;</span><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\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">hike.photoCount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> photos&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</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></code></pre></div>\n","options":[{"text":"السطر 2، لأن <code dir=\"ltr\">Text</code> يجب أن يُغلَّف داخل <code dir=\"ltr\">Text</code> آخر.","why":"وجود <code dir=\"ltr\">Text</code> مباشرة داخل <code dir=\"ltr\">View</code> هو الحالة الطبيعية. النصوص الخام وحدها تحتاج إلى تغليف."},{"text":"السطر 3، حين تكون <code dir=\"ltr\">photoCount</code> صفرًا، لأن <code dir=\"ltr\">0 &amp;&amp; …</code> تُقيَّم إلى <code dir=\"ltr\">0</code> فترسمها React كنصّ داخل View.","why":"صحيح. القيم <code dir=\"ltr\">false</code> و<code dir=\"ltr\">null</code> و<code dir=\"ltr\">undefined</code> لا ترسم شيئًا، لكن الرقم 0 يُرسم بوصفه “0”. استخدم <code dir=\"ltr\">photoCount &gt; 0 &amp;&amp; …</code>."},{"text":"لا هذا ولا ذاك؛ React Native يتجاهل النصوص الشاردة بصمت.","why":"لا يفعل. على الويب يصبح النص الشارد عقدة نصية، لكن الـ View الأصلي ليس فيه عقدة نصية يضعه فيها، فيرمي React Native خطأ."}],"answer":1},{"q":"<p>وضعت <code dir=\"ltr\">style={{ color: '#2f6f4e', fontSize: 18 }}</code> على <code dir=\"ltr\">View</code>. ماذا يحدث للـ <code dir=\"ltr\">Text</code> الذي بداخله؟</p>","options":[{"text":"يصبح أخضر بحجم 18 نقطة، كما في الوراثة في CSS.","why":"لا يوجد cascade من View إلى Text. الـ Text يرث فقط من Text أعلى منه."},{"text":"ينهار التطبيق لأن View لا يقبل هذه المفاتيح.","why":"ستحصل على خطأ type في TypeScript، لكن وقت التشغيل يتجاهل الـ View هذه المفاتيح. المشكلة الحقيقية أن شيئًا لا يحدث."},{"text":"لا يتغيّر شيء؛ يحتفظ الـ Text بلونه وحجمه الافتراضيين.","why":"صحيح. ضع تنسيقات النص على الـ Text نفسه، أو ابنِ component صغيرًا باسم <code dir=\"ltr\">&lt;AppText&gt;</code> يطبّقها."}],"answer":2},{"q":"<p><code dir=\"ltr\">&lt;Image source={{ uri: hike.photoUrl }} /&gt;</code> لا يعرض شيئًا، ولا توجد أخطاء. ما الإصلاح الأرجح؟</p>","options":[{"text":"أعطِه حجمًا، مثل <code dir=\"ltr\">style={{ width: '100%', height: 220 }}</code>.","why":"صحيح. لا يستطيع React Native معرفة حجم صورة من الشبكة قبل تنزيلها، فدون حجم تكون الصورة 0 في 0."},{"text":"غلّف الرابط بـ <code dir=\"ltr\">require()</code>.","why":"<code dir=\"ltr\">require()</code> للصور المضمّنة في التطبيق، ويُحَلّ وقت البناء. لا يستطيع تحميل رابط."},{"text":"استخدم <code dir=\"ltr\">src</code> بدلًا من <code dir=\"ltr\">source</code>.","why":"<code dir=\"ltr\">src</code> هي سمة HTML. أما Image في React Native فيستخدم <code dir=\"ltr\">source</code>."}],"answer":0},{"q":"<p>شاشة التفاصيل في Trailhead فيها صورة وعنوان وإحصاءات ووصف طويل قد لا يتّسع. أيّ حاوية هي الأنسب؟</p>","options":[{"text":"<code dir=\"ltr\">View</code> مع <code dir=\"ltr\">overflow: 'scroll'</code>.","why":"الـ Views لا تتمرّر أبدًا مهما كانت قيمة overflow. التمرير component أصلي مستقل."},{"text":"<code dir=\"ltr\">ScrollView</code>، لأنها شاشة ثابتة من محتوى متنوّع.","why":"صحيح. ScrollView بحجم الشاشة مع عدد قليل من الأبناء هو بالضبط ما صُمّم له."},{"text":"<code dir=\"ltr\">FlatList</code> بعنصر واحد لكل فقرة.","why":"FlatList مخصّص لقوائم البيانات الطويلة المتجانسة. لشاشة محتوى واحدة يضيف تعقيدًا دون أي فائدة."}],"answer":1}],"exercise":{"kind":"spot-bug","language":"tsx","code":"import { Image, ScrollView, Text, View } from 'react-native';\n\nexport function HikeSummary({ hike }) {\n  return (\n    <ScrollView contentContainerStyle={{ padding: 16, gap: 12 }}>\n      <Image\n        source={{ uri: hike.photoUrl }}\n        style={{ width: '100%', height: 200 }}\n      />\n      <Text style={{ fontSize: 24, fontWeight: '700' }}>{hike.name}</Text>\n      <View style={{ flexDirection: 'row', gap: 12 }}>\n        <Text>{hike.distanceKm} km</Text>\n        {hike.elevationM} m up\n      </View>\n      {hike.photoCount && <Text>{hike.photoCount} photos</Text>}\n      <Text numberOfLines={3}>{hike.notes}</Text>\n    </ScrollView>\n  );\n}","bugLines":[13,15],"title":"اعثر على الانهيارين في ملخّص الرحلة","prompt":"<p>يظهر الـ component المسمّى <code dir=\"ltr\">HikeSummary</code> لكل رحلة في Trailhead. يعمل مع بعض الرحلات، ويُظهر شاشة الخطأ الحمراء مع رحلات أخرى، دائمًا مع الرسالة <strong>Text strings must be rendered within a <Text> component</strong>. اختر <strong>السطرين</strong> اللذين قد يسبّبان هذا الخطأ.</p>\n","hints":["ابحث عن أي شيء قد ينتهي به الأمر نصًّا خامًا أو رقمًا داخل <code dir=\"ltr\">View</code> أو <code dir=\"ltr\">ScrollView</code> مباشرة.","إحدى المشكلتين تحدث مع كل رحلة؛ والأخرى فقط مع الرحلات التي لها قيمة معيّنة.","إلى ماذا تُقيَّم <code dir=\"ltr\">0 &amp;&amp; anything</code>؟"],"explanation":"<p>السطر 13 يضع <code dir=\"ltr\">{hike.elevationM} m up</code> داخل <code dir=\"ltr\">View</code> مباشرة، فيفشل مع كل رحلة: غلّفه هكذا <code dir=\"ltr\">&lt;Text&gt;{hike.elevationM} m up&lt;/Text&gt;</code>. والسطر 15 يفشل فقط مع الرحلات التي لا صور لها: <code dir=\"ltr\">0 &amp;&amp; …</code> تُقيَّم إلى <code dir=\"ltr\">0</code>، فتحاول React رسمها كنصّ داخل الـ ScrollView. استخدم قيمة منطقية حقيقية: <code dir=\"ltr\">{hike.photoCount &gt; 0 &amp;&amp; &lt;Text&gt;{hike.photoCount} photos&lt;/Text&gt;}</code>. أما الـ <code dir=\"ltr\">Image</code> الذي يحمّل من الشبكة فسليم لأن له عرضًا وارتفاعًا صريحين.</p>\n","checkLabels":{}},"words":649,"readMinutes":4}