{"id":"l-rf-1-1","courseId":"react-fundamentals","lang":"ar","kind":"intro","summary":"افهم المشكلة التي تحلّها React، وما معنى أن تكون «الواجهة دالةً في الـ state»، وما الذي ستبنيه وتنشره بنهاية هذه الدورة.","html":"<p>على الأرجح كتبتَ من قبل شيئًا من JavaScript يغيّر الصفحة: تجد عنصرًا، تضبط نصّه، تضيف class، تُلحق عنصرًا بالقائمة. هذا ينجح مع زر واحد. ثم تضيف عدّادًا في الترويسة يجب أن يطابق القائمة، وفلترًا يُخفي بعض العناصر، ورسالة تظهر حين تكون القائمة فارغة. صارت كل نقرة مضطرة لتحديث أربعة أماكن بالترتيب الصحيح، وفي اليوم الذي تنسى فيه واحدًا منها، ستقول الترويسة «3 to watch» بينما القائمة تعرض فيلمين فقط.</p>\n<p>هذه المحاسبة اليدوية هي المشكلة التي بُنيت React لإزالتها.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">صِف النتيجة، لا الخطوات</h2>\n<p>مع React تكتب components (مكوّنات): دوال JavaScript تستقبل بعض البيانات وتُرجع وصفًا للشاشة. عندما تتغيّر البيانات، تستدعي React دوالك من جديد، وتقارن الوصف الجديد بالسابق، ولا تجري في الـ DOM إلا التغييرات اللازمة للانتقال من أحدهما إلى الآخر.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">src/App.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\"> WatchCount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">movies</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\"> left</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> movies.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">m</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> !</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">m.watched).</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">length</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\">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\">left</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> to watch&#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>لا يوجد في أي مكان كود من نوع «عندما يُعلَّم فيلم كمُشاهَد، اعثر على الترويسة وأنقص الرقم». العدد يُحسب من القائمة في كل مرة، لذلك لا يمكن أن يخرج عن التزامن معها. يلخّص الناس هذه الفكرة بعبارة <strong>الواجهة دالةٌ في الـ state</strong>: البيانات نفسها تُنتج دائمًا الشاشة نفسها.</p>\n<p>هذه الفكرة الواحدة تفسّر معظم ما ستتعلّمه. الـ props هي طريقة دخول البيانات إلى الـ component. والـ state (حالة المكوّن) بيانات تتغيّر مع الوقت. والأحداث هي طريقة المستخدم في طلب تغيير. والـ effects هي طريقتك للتزامن مع أشياء خارج React، مثل عنوان الصفحة أو localStorage.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">لماذا React، ولماذا الآن</h2>\n<p>هناك بدائل جيدة (Vue وSvelte وSolid وAngular)، والأفكار تنتقل بينها بسهولة. لكن React ما زالت الخيار الآمن لمن يتحوّل إلى البرمجة، لثلاثة أسباب عملية: تظهر في إعلانات وظائف الواجهات الأمامية أكثر من أي شيء آخر، ولديها أكبر منظومة من المكتبات والإجابات الجاهزة، وReact Native تتيح لك استخدام المهارات نفسها لبناء تطبيقات الجوّال.</p>\n<p>React 19 هو الإصدار الرئيسي الحالي، وقد جعل بعض الأمور أبسط: أصبح <code dir=\"ltr\">ref</code> مجرّد prop عادي، وحصلت النماذج على دعم مباشر عبر Actions، ويمكن لـ React Compiler الاختياري أن يتولّى عنك كثيرًا من تحسينات الأداء. ستلتقي بكل واحدة من هذه حيث تهمّ فعلًا، من دون حفظ التاريخ. أمّا الدروس القديمة التي تستخدم Create React App أو الـ class components فقد تجاوزها الزمن؛ تخطَّها.</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>ما تحتاجه على جهازك</span></p>\n<p>إصدار LTS حالي من Node.js (22 أو 24)، ومحرّر كود مثل VS Code، ومتصفّح حديث. ستجهّز كل ما عدا ذلك في الدرس التالي.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">ما الذي ستبنيه</h2>\n<p>الدورة كلها تبني تطبيقًا واحدًا: <strong>Watchlist</strong> للأفلام التي تريد مشاهدتها. في النهاية سيتيح لك إضافة فيلم من خلال نموذج، وتعليمه كمُشاهَد، وتصفية القائمة حسب الحالة، وحفظ كل شيء في localStorage حتى لا يمحوه تحديث الصفحة. وفي القسم الأخير تنسّقه باستخدام Tailwind CSS وتنشره على Vercel، فتنتهي برابط حقيقي تضعه في سيرتك الذاتية.</p>\n<p>ينتهي أغلب الدروس بتمرين عملي في ساحة التجربة داخل المتصفّح. لا تتخطَّ هذه التمارين. القراءة عن الـ state شيء، ومشاهدة زرّك وهو يرفض التحديث ثم اكتشاف السبب بنفسك شيء مختلف تمامًا.</p>\n<p>في الدرس التالي تجهّز مشروعًا حقيقيًا على جهازك باستخدام Vite، وترى أين تعيش React فعليًا داخله.</p>\n","toc":[{"id":"sec-1","text":"صِف النتيجة، لا الخطوات","level":2},{"id":"sec-2","text":"لماذا React، ولماذا الآن","level":2},{"id":"sec-3","text":"ما الذي ستبنيه","level":2}],"takeaways":["تتيح لك React أن تصف شكل الشاشة لكل حالة من البيانات، وهي تتولّى معرفة التغييرات المطلوبة في الـ DOM.","تطبيق React شجرة من الـ components، وكل component دالة JavaScript عادية تُرجع markup.","React 19 هو الإصدار الرئيسي الحالي، وهذه الدورة تستخدمه مع Vite للتطوير وVercel للاستضافة.","تتعلّم ببناء تطبيق واحد، Watchlist، تضيف إليه شيئًا جديدًا في كل درس."],"further":[{"title":"Quick Start (react.dev)","url":"https://react.dev/learn"},{"title":"Thinking in React","url":"https://react.dev/learn/thinking-in-react"}],"quiz":[{"q":"<p>ما المعنى العملي لعبارة «الواجهة دالةً في الـ state»؟</p>","options":[{"text":"تكتب كودًا يعدّل عُقد الـ DOM خطوة بخطوة كلما تغيّرت البيانات.","why":"هذا هو الأسلوب الأمري (imperative) الذي جاءت React لتحلّ محلّه. مع React تصف النتيجة، لا الخطوات الموصلة إليها."},{"text":"تصف شكل الشاشة للبيانات الحالية، وتحدّث React الـ DOM ليطابق هذا الوصف.","why":"صحيح. أنت تغيّر البيانات، وReact تعيد تشغيل الـ components وتطبّق الفروقات فقط على الصفحة."},{"text":"كل تغيير في البيانات يعيد تحميل الصفحة كاملة من الخادم.","why":"تحدّث React الصفحة في مكانها داخل المتصفّح. لا يُعاد تحميل شيء، ولا تُمسّ إلا عُقد الـ DOM التي تغيّرت."}],"answer":1},{"q":"<p>يعرض تطبيق Watchlist عبارة «3 to watch» في الترويسة، ويميّز الأفلام غير المشاهدة في القائمة. ثم يُعلَّم أحد الأفلام كمُشاهَد. ما الذي يحدث عادةً بشكل خاطئ مع كود DOM العادي؟</p>","options":[{"text":"يرفض المتصفّح تحديث مكانين داخل معالج نقرة واحد.","why":"يستطيع المتصفّح تحديث أي عدد من العُقد. المشكلة أن تتذكّر أنت فعل ذلك في كودك."},{"text":"لا يمكن تغيير قائمة الأفلام بعد تحميل الصفحة.","why":"يمكن دائمًا تغيير الـ DOM. المشكلة هي إبقاء كل مكان متغيّر متزامنًا يدويًا."},{"text":"يُنسى أحد الأماكن التي تعتمد على البيانات، فتختلف الترويسة عن القائمة.","why":"صحيح. كل ميزة جديدة تضيف مكانًا آخر يجب إبقاؤه متزامنًا. React تزيل هذه المحاسبة اليدوية، لأن الاثنين يُشتقّان من البيانات نفسها في كل render."}],"answer":2},{"q":"<p>أيّ عبارة عن React في 2026 صحيحة؟</p>","options":[{"text":"React 19 هو الإصدار الرئيسي الحالي، وVite طريقة شائعة لبدء تطبيق React يعمل في المتصفّح.","why":"صحيح. توثيق React يوجّهك إلى إطار عمل أو أداة بناء مثل Vite، وCreate React App أصبح متوقّفًا (deprecated)."},{"text":"يجب تفعيل React Compiler قبل أن يعمل React 19.","why":"الـ React Compiler تحسين اختياري وقت البناء. React 19 يعمل بشكل طبيعي من دونه."},{"text":"الـ class components ضرورية لأي component يحتوي على state.","why":"الـ function components مع hooks مثل useState هي الطريقة المعتمدة لكتابة components ذات state منذ سنوات."}],"answer":0}],"exercise":{"kind":"choice","multiple":true,"options":["derive-in-render","counter-variable","read-dom","derive-in-child"],"correct":["derive-in-render","derive-in-child"],"title":"أيّ عدّاد لا يمكن أن ينحرف؟","prompt":"<p>تعرض ترويسة Watchlist عدد الأفلام التي لم تُشاهَد بعد. يستطيع المستخدمون إضافة أفلام وحذفها وتعليمها كمُشاهَدة. <strong>اختر كل تصميم لا يمكن فيه أبدًا أن تختلف الترويسة عن القائمة.</strong></p>\n","hints":["اسأل عن كل تصميم: هل توجد نسخة ثانية من الرقم يجب على أحد أن يتذكّر تحديثها؟","القيمة التي تُحسب من القائمة في كل مرة تُعرض فيها ليست لها نسخة ثانية يمكن نسيانها."],"explanation":"<p>التصميمان الصحيحان كلاهما <strong>يشتقّ</strong> العدد من القائمة كلما رُسمت الشاشة، فيبقى للحقيقة مصدر واحد فقط: مصفوفة الأفلام. أمّا التصميمان الآخران فيحتفظان بنسخة ثانية من الرقم (في متغيّر أو في الـ DOM)، ويعتمدان على أن يحدّثها كل معالج أحداث، الآن وفي المستقبل، بشكل صحيح. وهذه بالضبط هي المحاسبة اليدوية التي صُمّمت React لإزالتها.</p>\n","checkLabels":{},"optionText":{"derive-in-render":{"text":"تحسب الترويسة <code dir=\"ltr\">movies.filter((m) =&gt; !m.watched).length</code> في كل render.","why":"صحيح. يُعاد حساب الرقم من القائمة في كل render، فلا يوجد شيء منفصل يجب إبقاؤه متزامنًا."},"counter-variable":{"text":"متغيّر <code dir=\"ltr\">leftCount</code> يبدأ بطول القائمة، وكل معالج نقرة يضيف إليه 1 أو يطرح منه 1.","why":"هذا يحتفظ بنسخة ثانية من الحقيقة. انسَ تعديله في معالج واحد (حذف فيلم مُشاهَد مثلًا) وستصبح الترويسة خاطئة."},"read-dom":{"text":"كل معالج يقرأ الرقم المعروض حاليًا في الترويسة، ثم يغيّره ويكتبه من جديد.","why":"يصبح الـ DOM هو مصدر الحقيقة، وأي معالج ينسى تعديله يترك الشاشة غير متزامنة مع البيانات."},"derive-in-child":{"text":"component اسمه <code dir=\"ltr\">WatchCount</code> يستقبل قائمة الأفلام ويحسب الرقم بنفسه.","why":"صحيح. إنها الفكرة نفسها منقولة إلى component خاص بها: العدد يأتي من القائمة، لا من حصيلة منفصلة."}}},"words":464,"readMinutes":3}