بناء موجز إشعارات في الوقت الفعلي
اجمع بين SSE وحالة React لبناء موجز إشعارات يتحدّث في الوقت الفعلي دون تفاعل من المستخدم
بناء موجز إشعارات في الوقت الفعلي درس مجاني في React Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Academy 4 دروس في المجموع.
بنية موجز الإشعارات
يجمع موجز الإشعارات الآني بين دفق SSE للإشعارات الواردة ونقاط REST الطرفية لتمييز العناصر كمقروءة. يحتفظ المكوّن بحالة محلية لقائمة الإشعارات، ويشترك في دفق الخادم عبر EventSource داخل useEffect، ويتعامل مع تفاعلات المستخدم (تمييز كمقروء وإخفاء) باستخدام تحديثات متفائلة.
بنية بيانات الإشعار
يكون كائن الإشعار عادةً بهذه البنية: { id: string, type: 'info' | 'warning' | 'success', message: string, timestamp: string, read: boolean }. ويحدد الحقل type الأيقونة واللون. ويتتبع الحقل read ما إذا كان المستخدم قد أقرّ الإشعار. ويتيح الحقل timestamp تجميع الإشعارات حسب الفترة الزمنية.
الاشتراك في دفق SSE
أنشئوا داخل useEffect كائن EventSource متصلًا بـ /api/notifications/stream. وعند كل حدث message، حللوا JSON وأضيفوا الإشعار الجديد إلى بداية الحالة: setNotifications(prev => [JSON.parse(e.data), ...prev]). يؤدي الإضافة إلى البداية (سلوك unshift) إلى وضع أحدث إشعار في الأعلى، وهو الأسلوب المعتاد في موجزات الإشعارات.
شارة عدد الإشعارات غير المقروءة
استنتجوا عدد الإشعارات غير المقروءة من مصفوفة الإشعارات من دون حالة إضافية: const unreadCount = notifications.filter(n => !n.read).length. اعرضوا هذا العدد كشَارة على أيقونة جرس الإشعارات. سيتحدث العدد تلقائيًا كلما تغيرت حالة الإشعارات، ولا حاجة إلى إدارة حالة منفصلة.
تمييز الإشعار كمقروء باستخدام تحديث متفائل
عندما ينقر المستخدم على إشعار، طبّقوا تحديث القراءة المتفائل فورًا: setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n)). ثم أرسلوا طلب PATCH إلى /api/notifications/:id مع { read: true } في الخلفية. تراجعوا عن التحديث المتفائل إذا فشل الطلب.
تجميع الإشعارات حسب الوقت
جمّعوا الإشعارات لعرضها ضمن مجموعات: «اليوم» (في اليوم التقويمي نفسه)، و«الأمس»، و«أقدم». احسبوا المجموعة باستخدام الطابع الزمني للإشعار والتاريخ الحالي: const today = new Date().toDateString(). اعرضوا كل مجموعة كقسم منفصل مع تسمية في ترويسته. ويسهّل ذلك استعراض قائمة طويلة من الإشعارات كثيرًا.
الإشعارات المنبثقة للنشاط في الخلفية
عندما يكون المستخدم في صفحة مختلفة ويصل إشعار جديد عبر SSE، اعرضوا إشعارًا منبثقًا بدلًا من تحديث قائمة الإشعارات أو بالإضافة إليه. استخدموا سياق إشعارات عامًا أو مخزن Zustand يمكن لكل من مشترك SSE ومُصيّر الإشعارات المنبثقة الوصول إليه. يختفي الإشعار المنبثق بعد بضع ثوانٍ، بينما يبقى الإشعار في القائمة.
سياق الإشعارات العام
بالنسبة إلى الإشعارات التي تظهر في أنحاء التطبيق، خزّنوها في سياق React أو مخزن Zustand على مستوى جذر التطبيق. ويكون اشتراك SSE في مكوّن موفّر قريب من أعلى شجرة المكوّنات. ويمكن لأي مكوّن قراءة الإشعارات أو إرسال إشعارات جديدة عبر المخزن المشترك، مما يتيح عرض الإشعارات المنبثقة من أي صفحة.
إعادة اتصال SSE عند التركيز على علامة التبويب
يتولى EventSource إعادة الاتصال تلقائيًا عند انقطاع الشبكة، لكن تغيّر مستوى ظهور علامة التبويب يختلف عن ذلك. فعندما يعود المستخدم إلى علامة تبويب بعد غياب طويل، قد يكون الخادم قد أنهى اتصال SSE. يعيد EventSource الاتصال تلقائيًا، وتعيد آلية Last-Event-ID تشغيل أي إشعارات فاتت المستخدم أثناء وجود علامة التبويب في الخلفية.
الاحتفاظ بالإشعارات أثناء التنقل
تفقد تطبيقات الصفحة الواحدة حالة الإشعارات الموجودة في الذاكرة عند الانتقال بعيدًا عن الصفحة. خزّنوا الإشعارات في localStorage بعد كل تحديث: localStorage.setItem('notifications', JSON.stringify(notifications)). وعند التركيب، ابدؤوا الحالة من localStorage قبل اتصال دفق SSE. ويحافظ ذلك على سجل الإشعارات أثناء التنقل بين الصفحات.
نمط نقطة SSE الطرفية
يجب أن تضبط نقطة SSE الطرفية على الخادم ترويسات محددة: Content-Type: text/event-stream وCache-Control: no-cache وConnection: keep-alive. في Express/NestJS، اكتبوا الأحداث بالشكل data: ${JSON.stringify(payload)}
؛ لاحظوا السطرين الجديدين اللذين يشيران إلى نهاية الحدث. ويجب على الخادم تفريغ المخزن المؤقت بعد كل عملية كتابة لضمان وصول الحدث إلى المتصفح فورًا.
نمط نقطة دفق SSE الطرفية
ما قيمة ترويسة Content-Type الصحيحة لنقطة SSE (الأحداث المرسلة من الخادم) الطرفية؟
مراجعة الدرس: موجز الإشعارات الآني
تجمع موجزات الإشعارات بين الاشتراك في SSE (استخدام useEffect مع تنظيف EventSource) وتعديلات REST (استخدام PATCH للتمييز كمقروء). بنية البيانات: {id, type, message, timestamp, read}. استنتجوا unreadCount باستخدام filter، وجمّعوا الإشعارات حسب اليوم/الأمس/الأقدم لعرضها. استخدموا سياقًا عامًا أو Zustand للإشعارات المنبثقة عبر الصفحات. واحفظوا البيانات في localStorage للحفاظ عليها أثناء التنقل. تتطلب نقطة SSE الطرفية Content-Type: text/event-stream وCache-Control: no-cache وفواصل أحداث مكوّنة من سطرين جديدين.
الأسئلة الشائعة
هل درس «بناء موجز إشعارات في الوقت الفعلي» مجاني؟
نعم — نص درس «بناء موجز إشعارات في الوقت الفعلي» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Academy 4 دروس في المجموع.
ماذا ستتعلم في «بناء موجز إشعارات في الوقت الفعلي»؟
اجمع بين SSE وحالة React لبناء موجز إشعارات يتحدّث في الوقت الفعلي دون تفاعل من المستخدم تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ React Academy؟
لا تُشترط خبرة سابقة. React Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «بناء موجز إشعارات في الوقت الفعلي»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس React Academy هذا؟
نعم. كل درس في React Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مقارنة SSE وWebSockets وPolling
- استهلاك تدفقات SSE في React باستخدام EventSource
- نمط الاستطلاع الطويل ومنطق إعادة الاتصال
- بناء موجز إشعارات في الوقت الفعلي