📋 مقدمة: ليه تطبيق المهام هو أفضل مشروع تبدأ بيه؟
تطبيق إدارة المهام (Todo App) هو المشروع الأكثر شيوعاً بين مطوري React المبتدئين، وده مش بسبب بساطته فقط، لكن لأنه يغطي 90% من المفاهيم الأساسية اللي هتحتاجها في أي تطبيق React حقيقي. في هذا الدرس، هنبني تطبيق مهام كامل من الصفر باستخدام Components, Props, State, useEffect، وكمان هنحفظ البيانات في المتصفح عشان ماتضيعش لما تغلق الصفحة.
بنهاية هذا الدرس، هتكون قادر على:
- تقسم أي تطبيق React إلى مكونات (Components) صغيرة ومنظمة
- تستخدم
useStateلإدارة حالة التطبيق بفعالية - تمرر البيانات والدوال بين المكونات باستخدام Props
- تحفظ البيانات في
localStorageباستخدامuseEffect - تتعامل مع النماذج (Forms) والمدخلات في React
📁 هيكل المشروع الكامل
قبل ما نبدأ في الكتابة، لازم نخطط لهيكل الملفات. التنظيم الجيد يسهل عليك صيانة المشروع لاحقاً ويجعل الكود مقروء للمطورين التانيين. في مشروعنا، هنقسم التطبيق إلى 4 مكونات رئيسية:
1️⃣ App.js - المكون الرئيسي وإدارة الحالة
المكون App.js هو "عقل" التطبيق. هنا بنخزن كل المهام في useState، ونعمل الدوال اللي بتضيف وتمسح وتعدل المهام. الميزة المهمة هنا إننا بنستخدم Initializer Function في useState عشان نقرأ البيانات من localStorage لما التطبيق يفتح لأول مرة.
🔍 شرح الكود:
- السطر 4-7: بنقرأ المهام المحفوظة في
localStorageلما التطبيق يفتح. لو مفيش بيانات، بنرجع مصفوفة فارغة[]. - السطر 10-12:
useEffectبيشتغل كل مرة المهام تتغير، وبيحفظها فيlocalStorageعشان ماتضيعش. - السطر 14-22: دالة
addTodoبتضيف مهمة جديدة معidفريد باستخدامDate.now(). - السطر 24-28: دالة
toggleTodoبتقلب حالة المهمة (منجزة/غير منجزة) باستخدامmapوspread operator.
2️⃣ TodoForm.js - نموذج إضافة مهمة مع التحقق
المكون TodoForm مسؤول عن استقبال المدخلات من المستخدم. الميزة المهمة هنا إننا بنستخدم Controlled Component (القيمة مربوطة بـ State)، وكمان بنمنع إرسال المهام الفارغة باستخدام trim().
3️⃣ TodoItem.js - عرض مهمة واحدة مع التفاعل
كل مهمة عبارة عن مكون مستقل يستقبل البيانات عبر Props ويرسل الأحداث للأب عبر دوال الـ Callback. بنستخدم Conditional CSS Classes عشان نغير شكل المهمة المنجزة.
4️⃣ TodoStats.js - إحصائيات المهام في الوقت الفعلي
المكون ده بيحسب الإحصائيات بشكل ديناميكي كل مرة المهام تتغير. بنستخدم filter عشان نعد المهام المنجزة، وبنستخدم useMemo لو كنت عايز تحسين الأداء مع عدد كبير من المهام.
🎯 ما تعلمته من هذا المشروع
بعد بناء هذا المشروع، أصبحت تفهم المفاهيم التالية بشكل عملي:
- State Management: إدارة حالة التطبيق باستخدام
useState- فهمت إزاي State في React immutable (مش بتتغير مباشرة)، وإنك لازم تستخدم الدوال المحدثة زيsetTodos. - Component Composition: تقسيم التطبيق إلى مكونات صغيرة مسؤولة عن مهمة واحدة فقط (Single Responsibility Principle).
- Props Communication: تمرير البيانات من الأب للابن عبر Props، وتمرير الدوال من الابن للأب عبر Callback Props.
- Array Operations: استخدام
mapلتحديث عنصر،filterلحذف عنصر، وspread operator [...]لإضافة عنصر. - localStorage: حفظ البيانات في المتصفح باستخدام
JSON.stringifyوJSON.parse. - useEffect: التعامل مع الآثار الجانبية مثل حفظ البيانات أو جلب بيانات من API.
- Form Handling: معالجة النماذج باستخدام Controlled Components ومنع السلوك الافتراضي بـ
preventDefault. - Conditional Rendering: إظهار/إخفاء عناصر بناءً على الشروط (زي زر "حذف المهام المنجزة" اللي يظهر بس لو فيه مهام منجزة).
⚠️ أخطاء شائعة وتجنبها
❌ الخطأ 1: تعديل State مباشرة
غلط: todos.push(newTodo) - ده بيعدل المصفوفة الأصلية وReact مش هتشوف التغيير.
صح: setTodos([...todos, newTodo]) - بنعمل نسخة جديدة من المصفوفة.
❌ الخطأ 2: نسيان Dependency Array في useEffect
غلط: useEffect(() => { ... }) - ده بيشتغل مع كل render ويسبب loop لانهائي.
صح: useEffect(() => { ... }, [todos]) - بنحدد متى يشتغل.
❌ الخطأ 3: استخدام index كـ Key
غلط: <TodoItem key={index} /> - لو حذفت عنصر، الـ index بتتغير وReact بيحصل confusion.
صح: <TodoItem key={todo.id} /> - استخدم ID فريد ثابت.
💡 التحسينات المستقبلية
بعد ما تتقن المشروع الأساسي، جرب تضيف الميزات دي عشان ترفع مستواك:
- تصنيفات (Categories): أضف حقل
categoryلكل مهمة (عمل، شخصي، دراسة) وخلي المستخدم يفلتر حسب التصنيف. - الأولوية: أضف أيقونات ⭐ للمهام المهمة ورتبها حسب الأولوية.
- تواريخ الاستحقاق: أضف حقل
dueDateولو المهمة تأخرت، غير لونها للأحمر. - تصفية متقدمة: أزرار "الكل" / "المتبقية" / "المنجزة" عشان يسهل التنقل.
- البحث: حقل بحث يفلتر المهام حسب النص المكتوب.
- تحرير المهام: دبل-كليك على المهمة يحولها لـ input editable.
- Backend API: ربط التطبيق بـ Node.js + MongoDB عشان المهام تتحفظ على السيرفر وتتزامن بين الأجهزة.
📚 دروس ذات صلة
❓ أسئلة شائعة
هل يمكن استخدام useReducer بدلاً من useState في هذا المشروع؟
نعم، وده يُفضل فعلاً لو التطبيق هيكبر. useReducer مناسب أكتر لما يكون عندك حالة معقدة (زي إضافة + حذف + تعديل + تصفية). لكن في مشروع Todo App البسيط، useState أسهل وأوضح للمبتدئين.
هل localStorage آمن لحفظ البيانات الحساسة؟
لا، localStorage غير آمن للبيانات الحساسة (كلمات مرور، بيانات بنكية). أي شخص يقدر يفتح DevTools ويقرأ المحتوى. استخدمه للبيانات العامة بس زي قائمة المهام. للبيانات الحساسة، استخدم Backend مع تشفير.
إزاي أحول المشروع ده لتطبيق PWA (تطبيق ويب تقدر تثبته على الموبايل)؟
سهل! أضف ملف manifest.json و service-worker.js. React بيدعم PWA من الصندوق - استخدم npx create-react-app my-app --template cra-template-pwa في المشاريع الجديدة.