| وجه المقارنة المعمارية | الإدارة التقليدية لدورة الحياة (داخل المكونات عبر ngOnInit) | الاعتماد على خطافات المتجر (SignalStore Lifecycle Hooks) |
|---|---|---|
| مكان تنفيذ طلبات التهيئة والبدء | تُكتب داخل ملفات المكونات (`Component.ts`) مما يربط منطق الجلب بالعرض بصورة تشابكية | تُعزل تماماً داخل المتجر نفسه، مما يجعل المتجر مستقلاً وقابلاً لإعادة الاستخدام في أي مكان |
| إدارة تسريب الذاكرة والاشتراكات | تتطلب كتابة أكواد إضافية لإلغاء الاشتراكات (`unsubscribe`) يدوياً داخل `ngOnDestroy` | تتولى خطافات المتجر إدارة التنظيف التلقائي عند انتهاء سياق الحقن أو تدمير المتجر |
| فصل المسؤوليات (Separation of Concerns) | تتحمل المكونات أعباء إضافية تتعلق ببدء وتشغيل منطق البيانات | تكون المكونات خفيفة ونظيفة وكل مهمة تهيئة تخص البيانات تُدار مركزياً داخل المتجر |
لا تقتصر المخازن على تخزين الحالة فحسب، بل تمتد لتتولى مهام التهيئة والتحضير التلقائي عند إنشاء المتجر أو تنظيف الموارد عند تدميره. توفر خطافات دورة الحياة (Lifecycle Hooks) مثل onInit و onDestroy في NgRx SignalStore بيئة هندسية نظيفة لتشغيل طلبات جلب البيانات الأولية أو إيقاف الاشتراكات بشكل تلقائي ودون الحاجة لتكرار الكود داخل المكونات.
عندما يتم إنشاء المتجر (خاصة في الجذر أو ضمن سياق مكون محدد)، يتم تنفيذ خطاف onInit تلقائياً لتشغيل عمليات أساسية مثل جلب بيانات المستخدم أو استرجاع الإعدادات العامة من الخادم دون تدخل يدوي من المكون.
يتيح لك خطاف onDestroy إغلاق أي مؤقتات نشطة أو تفاعلات مرتبطة بالمتجر هندسياً بمجرد انتهاء دورة حياته، مما يحمي التطبيق من تسريبات الذاكرة (Memory Leaks).
⚠️ تحذير
تجنب إطلاق عمليات جانبية لا نهائية داخل onInit بدون شروط توقف! التأكد من ضبط شروط التشغيل أو استخدام دوال آمنة مثل rxMethod داخل الخطافات يمّنع حدوث حلقات تكرارية لا نهائية تستهلك موارد المتصفح وتؤدي إلى انهيار التطبيق.
| 1 | import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals'; |
| 2 | import { rxMethod } from '@ngrx/signals/rxjs-interop'; |
| 3 | import { pipe, tap, delay, of } from 'rxjs'; |
| 4 | |
| 5 | interface LifecycleState { |
| 6 | statusMessage: string; |
| 7 | isInitialized: boolean; |
| 8 | } |
| 9 | |
| 10 | export const LifecycleStore = signalStore( |
| 11 | { providedIn: 'root' }, |
| 12 | withState<LifecycleState>({ |
| 13 | statusMessage: 'في انتظار تهيئة المتجر...', |
| 14 | isInitialized: false |
| 15 | }), |
| 16 | withMethods((store) => ({ |
| 17 | initializeStore: rxMethod<void>( |
| 18 | pipe( |
| 19 | tap(() => patchState(store, { statusMessage: 'جاري تهيئة وتشغيل المتجر تلقائياً...' })), |
| 20 | delay(1000), |
| 21 | tap(() => patchState(store, { statusMessage: 'تم تهيئة المتجر بنجاح وجاهز للعمل', isInitialized: true })) |
| 22 | ) |
| 23 | ) |
| 24 | })), |
| 25 | // تفعيل خطافات دورة الحياة لإدارة العمليات التلقائية |
| 26 | withHooks({ |
| 27 | onInit(store) { |
| 28 | console.log('تم إنشاء المتجر وتفعيل خطاف onInit بنجاح'); |
| 29 | store.initializeStore(); |
| 30 | }, |
| 31 | onDestroy(store) { |
| 32 | console.log('تم تدمير المتجر وتنظيف الموارد تلقائياً عبر onDestroy'); |
| 33 | } |
| 34 | }) |
| 35 | ); |