{"id":"l-rf-4-4","courseId":"react-fundamentals","lang":"ar","kind":"wrapup","summary":"راجع ما صار بإمكانك بناؤه باستخدام React، ووسّع Watchlist بتحدّيات ملموسة، واختر الموضوعات التالية التي تتعلّمها بترتيب يبني على هذه الدورة.","html":"<p>قبل ثمانية عشر درسًا كان لديك مجلد فارغ. والآن لديك تطبيق منشور مبني من components صغيرة، فيه state يعيش في مكان واحد، وقيم مشتقّة لا يمكن أن تنحرف، ونموذج بتحقّق حقيقي من المدخلات، وeffect يحفظ البيانات وينظّف خلفه، وأنماط لم تضطر إلى كتابتها يدويًا، ورابط. والأهم من ذلك أنك تعرف <em>لماذا</em> اتُّخذ كل قرار من هذه القرارات، وهذا ما يتيح لك اتّخاذها من جديد في تطبيق مختلف.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">ما الذي تستطيع فعله الآن</h2>\n<p>عُد إلى الوعود الستة في صفحة الدورة، وطابق كل واحد منها مع شيء بنيته:</p>\n<ul>\n<li><strong>الـ components والـ props والـ state</strong>: كل جزء من Watchlist، من <code dir=\"ltr\">MovieItem</code> إلى <code dir=\"ltr\">App</code>.</li>\n<li><strong>بيئة عمل React 19 وVite</strong>: <code dir=\"ltr\">npm create vite@latest</code>، وخادم التطوير، و<code dir=\"ltr\">npm run build</code>.</li>\n<li><strong>الأحداث والنماذج والـ controlled inputs</strong>: نموذج إضافة الأفلام، مع التشذيب والتعطيل والمسح.</li>\n<li><strong>الـ effects بالطريقة الصحيحة</strong>: عنوان التبويب وlocalStorage، وكل الأماكن التي <em>لم</em> تستخدم فيها effect.</li>\n<li><strong>تركيب الشاشات من قطع صغيرة</strong>: <code dir=\"ltr\">Panel</code> و<code dir=\"ltr\">MovieList</code> والبقية، لكلٍّ منها بضعة props وعمل واضح.</li>\n<li><strong>النشر إلى الإنتاج</strong>: deployment على Vercel مع روابط معاينة لكل branch.</li>\n</ul>\n<h2 id=\"sec-2\" tabindex=\"-1\">اجعل Watchlist ملكك</h2>\n<p>أسرع طريقة لترسيخ ما تعلّمته أن تواصل بناء التطبيق نفسه، من دون درس يرشدك. كل واحد من هذه لا يستخدم إلا ما تعلّمته:</p>\n<ol>\n<li><strong>الترتيب</strong>: قائمة منسدلة لـ «Newest first» و«Title A–Z». قطعة state جديدة واحدة، وقائمة مشتقّة واحدة.</li>\n<li><strong>تعديل العنوان</strong>: انقر مرتين على عنوان ليتحوّل إلى حقل؛ Enter يحفظ، وEscape يلغي.</li>\n<li><strong>البحث</strong>: حقل نصي يصفّي حسب العنوان أثناء الكتابة، مع فلتر الحالة معًا.</li>\n<li><strong>التراجع عن الحذف</strong>: احتفظ بآخر فيلم محذوف واعرض زر «Undo» لبضع ثوانٍ. ستحتاج إلى مؤقّت داخل effect، مع دالة تنظيف.</li>\n<li><strong>اختصار لوحة المفاتيح</strong>: اضغط «/» لنقل التركيز إلى حقل الإضافة، مع مستمع على window داخل effect، و<code dir=\"ltr\">ref</code>.</li>\n</ol>\n<p>ارفع كل ميزة على branch خاص بها، وافحص رابط المعاينة قبل الـ merge، تمامًا كما يفعل فريق حقيقي.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">ما الذي تتعلّمه بعد ذلك</h2>\n<p>ترتيب يبني على هذه الدورة:</p>\n<ol>\n<li><strong>TypeScript.</strong> إضافة الأنواع إلى الـ props والـ state تلتقط فئة كاملة من الأخطاء قبل أن تشغّل أي شيء، ومعظم إعلانات وظائف React تتوقّعها. ابدأ مشروعًا بـ <code dir=\"ltr\">--template react-ts</code>، أو حوّل Watchlist ملفًا ملفًا. ودورة <a href=\"/ar/courses/advanced-typescript\">أنماط TypeScript المتقدّمة</a> تذهب أبعد بكثير حين ترتاح معها.</li>\n<li><strong>الاختبارات.</strong> يتيح لك Vitest مع React Testing Library رسم component، والنقر عليه كما يفعل المستخدم، والتحقّق من النتيجة. والـ components الصغيرة لديك سهلة الاختبار أصلًا. راجع دورة <a href=\"/ar/courses/testing-javascript\">اختبار تطبيقات JavaScript</a>.</li>\n<li><strong>مزيد من الـ hooks.</strong> <code dir=\"ltr\">useRef</code> للوصول إلى الـ DOM ولقيم لا تُطلق render، و<code dir=\"ltr\">useReducer</code> حين يكبر منطق التحديث، و<code dir=\"ltr\">useContext</code> للبيانات التي تحتاجها components كثيرة. أمّا React Compiler، وهو خطوة بناء اختيارية، فيتولّى معظم الـ memoization، فتعلّم <code dir=\"ltr\">useMemo</code> و<code dir=\"ltr\">memo</code> لكن لا تنثرهما في كل مكان.</li>\n<li><strong>جلب البيانات.</strong> التطبيقات الحقيقية تحمّل البيانات من الخوادم. الجلب داخل effect يصلح للحالات البسيطة إن تعاملت مع حالات السباق؛ وفي ما هو أكثر من ذلك، استخدم TanStack Query، التي تتولّى عنك التخزين المؤقّت وحالات التحميل والأخطاء.</li>\n<li><strong>التوجيه وأطر العمل.</strong> لعدّة صفحات، أضف React Router. وللـ server rendering وتحميل البيانات وReact Server Components، استخدم إطار عمل مثل Next.js أو وضع إطار العمل في React Router، كما يوصي توثيق React للتطبيقات الجديدة الكاملة.</li>\n</ol>\n<aside class=\"callout callout-tip\" 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=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تعلّم داخل مشروعك</span></p>\n<p>حين تدرس أداة جديدة، أضفها إلى Watchlist بدل أن تبدأ مشروعًا تعليميًا جديدًا. أنت تفهم أصلًا كل سطر في التطبيق، فيكون الشيء الجديد الوحيد هو الأداة نفسها.</p>\n</aside>\n<p>جئت إلى هنا لتبني واجهات تفاعلية باستخدام React. وقد بنيت واحدة ونشرتها. واصل البناء.</p>\n","toc":[{"id":"sec-1","text":"ما الذي تستطيع فعله الآن","level":2},{"id":"sec-2","text":"اجعل Watchlist ملكك","level":2},{"id":"sec-3","text":"ما الذي تتعلّمه بعد ذلك","level":2}],"takeaways":["الـ components والـ props والـ state والأحداث والـ effects هي جوهر React؛ وكل ما عداها يُبنى فوقها.","توسيع مشروعك الخاص بميزات جديدة هو أسرع طريقة لترسيخ هذه الدورة.","TypeScript والاختبارات هما المهارتان اللتان تغيّران أكثر من غيرهما نظرة أصحاب العمل إلى ملف أعمال مطوّر React مبتدئ.","لجلب البيانات وللتطبيقات متعدّدة الصفحات، استعن بأدوات راسخة مثل TanStack Query أو React Router أو إطار عمل، بدل أن تبني أدواتك الخاصة."],"further":[{"title":"React reference overview","url":"https://react.dev/reference/react"},{"title":"Creating a React App (frameworks)","url":"https://react.dev/learn/creating-a-react-app"},{"title":"React Compiler","url":"https://react.dev/learn/react-compiler"},{"title":"Getting Started with Vitest","url":"https://vitest.dev/guide/"}],"quiz":[{"q":"<p>تريد إضافة خيار «الترتيب حسب السنة» إلى Watchlist. بناءً على هذه الدورة، ما القرار التصميمي الأول الصحيح؟</p>","options":[{"text":"خزّن الترتيب المختار في الـ state، واحسب نسخة مرتّبة من الأفلام أثناء الـ render.","why":"صحيح. الترتيب المختار state حقيقي؛ أمّا القائمة المرتّبة فمشتقّة من الأفلام والترتيب، فلا ينبغي تخزينها."},{"text":"خزّن نسخة مرتّبة من الأفلام في الـ state وحدّثها بـ effect.","why":"هذا يكرّر قائمة الأفلام ويزامنها بـ effect، وهو بالضبط النمط الذي علّمتك الدورة تجنّبه."},{"text":"رتّب مصفوفة الأفلام في مكانها بـ <code dir=\"ltr\">sort</code> قبل الـ render.","why":"الترتيب في المكان يعدّل الـ state. استخدم <code dir=\"ltr\">toSorted</code> أو رتّب نسخة."}],"answer":0},{"q":"<p>يطلب إعلان وظيفة «React وTypeScript والاختبارات». أيّ خطوة تالية تضيف أكثر إلى مشروع Watchlist في ملف أعمالك؟</p>","options":[{"text":"إعادة كتابته بالـ class components لإظهار تنوّع خبرتك.","why":"الـ class components إرث قديم. وعرضها يوحي بمعرفة متقادمة بدل التنوّع."},{"text":"إضافة مزيد من مكتبات الحركة.","why":"اللمسات الجمالية مفيدة، لكنها لا تعالج المهارات التي يذكرها الإعلان."},{"text":"تحويله إلى TypeScript وإضافة بعض اختبارات الـ components باستخدام Vitest وReact Testing Library.","why":"صحيح. الـ props ذات الأنواع والاختبارات التي تمرّ بمسارات حقيقية هي ما يبحث عنه المراجعون في مشروع React لمطوّر مبتدئ."},{"text":"نقل كل الـ state إلى مكتبة store عامة.","why":"لا يحتاج Watchlist إلى store عام، وإضافته بلا سبب توحي بمعمارية منسوخة بلا فهم."}],"answer":2},{"q":"<p>فعّل فريقك React Compiler. ما الذي يتغيّر في الكود الذي تكتبه؟</p>","options":[{"text":"يجب أن تغلّف كل component بـ <code dir=\"ltr\">memo</code> حتى يعمل المترجم.","why":"يقوم المترجم بهذا النوع من الـ memoization نيابةً عنك؛ وإضافته يدويًا هو بالضبط ما يجعله غير ضروري."},{"text":"تواصل كتابة components عادية تتبع قواعد React، ويضيف المترجم الـ memoization وقت البناء.","why":"صحيح. إنه خطوة بناء اختيارية. وما يعتمد عليه هو الـ components النقية والاستخدام الصحيح للـ hooks، وهو ما تمارسه أصلًا."},{"text":"لم يعد مسموحًا بالـ effects.","why":"الـ effects ما زالت موجودة، وما زالت للتزامن مع الأنظمة الخارجية. المترجم لا يزيل أي hook."}],"answer":1}],"exercise":{"kind":"choice","multiple":true,"options":["fetch-in-render","effect-no-deps","effect-ignore-flag","tanstack-query"],"correct":["effect-ignore-flag","tanstack-query"],"title":"جلب الملصقات بالطريقة الصحيحة","prompt":"<p>أول ميزة توسيعية لك: حين تفتح تفاصيل فيلم، يجلب Watchlist رابط ملصقه من API للأفلام، باستخدام عنوان الفيلم المحدَّد. ويستطيع المستخدم التنقّل بالنقر بسرعة من فيلم إلى آخر.</p>\n<p><strong>اختر كل نهج سيعمل بشكل صحيح.</strong></p>\n","hints":["كل ما في جسم الـ component يُنفَّذ في كل render.","إذا بدّل المستخدم الأفلام بسرعة، فسيكون هناك طلبان قيد التنفيذ. أيّهما يجب أن يفوز؟"],"explanation":"<p>الجلب تزامن مع نظام خارجي، لذا فمكان النسخة المكتوبة يدويًا هو effect مرتبط بالعنوان، مع دالة تنظيف تعلّم الطلب القديم على أنه منتهي الصلاحية. وإلا فقد تصل استجابة بطيئة للفيلم السابق أخيرًا وتكتب فوق الملصق. ومكتبة جلب بيانات مثل TanStack Query تتولّى ذلك، إضافةً إلى التخزين المؤقّت وحالات التحميل والأخطاء، ولهذا تستخدم معظم المشاريع الحقيقية واحدة. أمّا الجلب أثناء الـ render أو داخل effect بلا مصفوفة اعتماديات فيرسل طلبًا في كل render، وضبط الـ state من الاستجابة يُطلق render آخر وطلبًا آخر، ولا شيء يمنع استجابة أقدم من أن تفوز.</p>\n","checkLabels":{},"optionText":{"fetch-in-render":{"text":"استدعِ <code dir=\"ltr\">fetch</code> في أعلى جسم الـ component، و<code dir=\"ltr\">setPoster</code> حين تكتمل.","why":"الجسم يُنفَّذ في كل render، فيرسل كل render (بما فيه الـ render الإضافي في StrictMode) طلبًا، وكل استجابة تضبط الـ state تسبّب render آخر وطلبًا آخر. يجب أن يبقى الـ render نقيًا."},"effect-no-deps":{"text":"اجلب داخل <code dir=\"ltr\">useEffect(() =&gt; { … })</code> بلا مصفوفة اعتماديات.","why":"من دون مصفوفة يعمل الـ effect بعد كل render، فكل استجابة تضبط الـ state تُطلق render آخر وطلبًا آخر، ولا شيء يمنع استجابة قديمة من الكتابة فوق الملصق الحالي."},"effect-ignore-flag":{"text":"اجلب داخل <code dir=\"ltr\">useEffect(…, [title])</code>، مع دالة تنظيف تضبط <code dir=\"ltr\">ignore = true</code> حتى لا تُحفظ استجابة قديمة.","why":"صحيح. يعيد الجلب فقط حين يتغيّر العنوان، ودالة التنظيف تمنع استجابة أقدم وأبطأ من الكتابة فوق الملصق الحالي."},"tanstack-query":{"text":"استخدم <code dir=\"ltr\">useQuery</code> من TanStack Query مع العنوان داخل مفتاح الاستعلام.","why":"صحيح. تتتبّع المكتبة الطلبات لكل مفتاح، وتتجاهل القديمة منها، وتضيف التخزين المؤقّت وحالات التحميل والأخطاء نيابةً عنك."}}},"words":533,"readMinutes":3}