أخطاء شائعة يقع فيها مطورو React وكيفية إصلاحها باحتراف

دقائق القراءة: 5

مقدمة

عند تطوير واجهات المستخدم باستخدام React، قد تبدو بعض الأخطاء بسيطة في البداية، لكنها تؤثر مباشرة في الأداء، واستقرار التطبيق، وتجربة المستخدم. في هذا المقال سنستعرض مجموعة من أكثر الأخطاء شيوعاً التي يقع فيها مطورو React، مع شرح عملي لكيفية تجنبها وكتابة شيفرة أوضح وأسهل في الصيانة.

مطور يعمل على تطبيق React ويحلل أخطاء برمجية شائعة في تطوير الواجهات

لا تنسَ أن تغيير المسار يؤدي إلى إلغاء تحميل المكوّن وتحميل آخر

عند استخدام التوجيه داخل تطبيق React، يتم تعريف المسارات غالباً داخل المكوّن Switch. وهذا يعني أن التطبيق يعرض مكوّناً واحداً فقط في كل مرة وفق المسار المطابق.

بناءً على ذلك، عند الانتقال من مسار إلى آخر، يتم إلغاء تحميل المكوّن السابق unmount ثم تحميل المكوّن الجديد mount. هذه النقطة مهمة جداً إذا كنت تعتمد على بيانات تريد الاحتفاظ بها أثناء التنقل بين الصفحات.

متى تظهر المشكلة؟

إذا خزّنت بيانات داخل مكوّن مرتبط بمسار معين، ثم انتقلت إلى مسار آخر، فغالباً ستفقد تلك البيانات عند العودة، لأن المكوّن الأصلي أُزيل من الواجهة ثم أُعيد إنشاؤه من جديد.

كيف تتجنب ذلك؟

  • ضع البيانات المشتركة داخل مكوّن أعلى يحتوي المسارات، مثل App.
  • استخدم وسائل تخزين دائمة مثل localStorage أو sessionStorage عند الحاجة.
  • فكّر في استخدام إدارة حالة مركزية إذا كانت البيانات تُستخدم في أكثر من جزء من التطبيق.

إذا كنت تراقب التنفيذ عبر console.log، فستلاحظ عند كل تغيير في المسار أن المكوّن السابق يُزال ثم يُحمّل مكوّن جديد، وهذا سلوك طبيعي يجب أخذه في الحسبان أثناء تصميم التطبيق.

لا تستخدم صيغة setState بشكل خاطئ

من الأخطاء المتكررة الخلط بين طريقة تحديث الحالة في المكوّنات المعتمدة على الأصناف class components وبين المكوّنات الوظيفية functional components.

في المكوّنات المعتمدة على الأصناف

تكون الحالة state كائناً object في العادة، مثل المثال التالي:

this.state = {
  counter: 0
};

وعند استخدام الصيغة المعتمدة على الحالة السابقة لتحديثها، تكون الكتابة بالشكل التالي:

this.setState((prevState) => {
  return {
    counter: prevState.counter + 1
  };
});

هنا المتغير prevState هو كائن، لذلك نصل إلى القيمة عبر prevState.counter.

في المكوّنات الوظيفية مع Hooks

عند استخدام useState، قد تكون الحالة قيمة بسيطة وليست كائناً، كما في المثال التالي:

const [counter, setCounter] = useState(0);

في هذه الحالة، تكون القيمة السابقة رقماً مباشراً، وليس كائناً يحتوي خاصية باسم counter. لذلك تكون الصيغة الصحيحة:

setCounter((prevCounter) => prevCounter + 1);

ويمكن اختصارها أكثر إلى:

setCounter((counter) => counter + 1);

لماذا هذا الخطأ شائع؟

لأن كثيراً من المطورين ينتقلون من أسلوب class إلى Hooks مع الاحتفاظ بنفس طريقة التفكير. لكن في useState، نوع البيانات هو الذي يحدد طريقة التعامل معها، وليس نمط واحد ثابت.

لا تستدعِ Hooks داخل المكوّنات المعتمدة على الأصناف

منذ الإصدار 16.8.0، قدمت React مفهوم Hooks لتسهيل إدارة الحالة ودورة حياة المكوّنات داخل المكوّنات الوظيفية.

ومن أشهر هذه الأدوات:

  • useParams للوصول إلى معاملات الرابط.
  • useHistory أو البدائل الحديثة للتعامل مع سجل التنقل.
  • useRef للوصول إلى عناصر DOM.

لكن القاعدة الأساسية هنا واضحة: جميع Hooks تعمل فقط داخل المكوّنات الوظيفية أو داخل custom hooks، ولا يمكن استخدامها داخل مكوّنات class.

ما الحل إذا كان المشروع قديماً؟

إذا كنت تعمل على شيفرة قديمة مبنية باستخدام class components وتحتاج إلى استخدام Hooks، فالحل الأفضل هو إعادة هيكلة المكوّن وتحويله إلى مكوّن وظيفي. هذا التغيير لا يسهّل فقط استخدام Hooks، بل يجعل الشيفرة غالباً أبسط وأوضح.

رسالة خطأ ناتجة عن محاولة استخدام Hooks داخل مكوّن class في React

لا تنسَ إضافة الخاصية key عند استخدام map

عند عرض قائمة عناصر في React، من الشائع استخدام الدالة map() للتكرار على المصفوفة وتحويل كل عنصر إلى مكوّن مرئي.

على سبيل المثال:

const Items = ({ items }) => (
  <ol>
    {items.map((item) => (
      <Item item={item} />
    ))}
  </ol>
);

هذه الصيغة ستؤدي إلى ظهور تحذير في وحدة التحكم، لأن كل عنصر ناتج عن map() يجب أن يمتلك خاصية key فريدة.

لماذا تحتاج React إلى key؟

تعتمد React على الخاصية key لمعرفة العناصر التي تغيّرت أو أُضيفت أو أُزيلت، وبالتالي تحسين عملية إعادة التصيير re-rendering وتجنب العمليات غير الضرورية.

الصيغة الصحيحة

<Item item={item} key={index} />

بهذه الطريقة يختفي التحذير، وتتمكن React من تتبع العناصر بشكل صحيح.

تحذير React بسبب غياب الخاصية key عند عرض قائمة باستخدام mapحل مشكلة missing key في React بعد إضافة الخاصية key للعناصر

ملاحظة مهمة حول استخدام index

استخدام index كمفتاح قد يكون مقبولاً إذا كانت العناصر ثابتة الترتيب ولا تُحذف ولا يُعاد ترتيبها. أما إذا كانت القائمة ديناميكية، فمن الأفضل استخدام معرّف فريد حقيقي مثل id، لأن ذلك يمنع أخطاء العرض غير المتوقعة.

لا تستخدم الدوال المضمّنة داخل الأحداث بطريقة خاطئة

من الأخطاء الشائعة أيضاً تمرير نتيجة استدعاء الدالة إلى الحدث بدلاً من تمرير دالة نفسها. هذا الخطأ قد يؤدي إلى تنفيذ الدالة فور التصيير بدلاً من انتظار نقر المستخدم.

لنفترض أن الحالة معرفة بالشكل التالي:

const [items, setItems] = useState(["one", "two"]);

ثم يتم عرض العناصر هكذا:

{items.map((item, index) => (
  <li key={index}>
    {item}
    <button onClick={handleRemoveItem(item)}>Remove</button>
  </li>
))}

في هذا المثال، لن يعمل السلوك كما هو متوقع، لأن التعبير handleRemoveItem(item) يُنفّذ مباشرة أثناء التصيير.

متى تمرر الدالة مباشرة؟

إذا كانت الدالة لا تحتاج إلى معاملات، فاستخدم:

<button onClick={handleRemoveItem}>Remove</button>

متى تستخدم دالة مضمنة inline function؟

إذا كنت بحاجة إلى تمرير قيمة محددة، فاستخدم دالة سهمية:

<button onClick={() => handleRemoveItem(item)}>Remove</button>

بهذا الأسلوب، لن تُنفذ الدالة إلا عند النقر على الزر، وهو السلوك الصحيح.

مثال يوضح الخطأ الناتج عن استخدام onClick بشكل غير صحيح في React

أفضل الممارسات لتجنب هذه الأخطاء في مشاريع React

  • افصل بين منطق الواجهة ومنطق البيانات بوضوح.
  • اختر مكان تخزين الحالة بعناية، خاصة إذا كانت مطلوبة عبر أكثر من مسار.
  • استخدم Hooks فقط ضمن السياق الصحيح.
  • أضف الخاصية key لكل عنصر متكرر داخل map().
  • راجع معالجات الأحداث وتأكد أنك تمرر دالة لا نتيجة تنفيذها.
  • راقب التحذيرات داخل وحدة التحكم، لأن React يقدم إشارات مفيدة جداً أثناء التطوير.

ملخص سريع للأخطاء والحلول

الخطأ السبب الحل
فقدان البيانات عند تغيير المسار إلغاء تحميل المكوّن عند الانتقال رفع الحالة إلى مكوّن أعلى أو استخدام تخزين دائم
استخدام خاطئ لـ setState الخلط بين class وHooks التعامل مع القيمة السابقة حسب نوعها الحقيقي
استدعاء Hooks داخل class مخالفة قواعد React تحويل المكوّن إلى مكوّن وظيفي
غياب key في القوائم عدم قدرة React على تتبع العناصر بدقة استخدام مفتاح فريد لكل عنصر
تنفيذ الدالة مباشرة داخل onClick تمرير ناتج الاستدعاء بدل الدالة استخدام دالة مباشرة أو دالة سهمية عند الحاجة إلى معاملات

بانر تعليمي لمحتوى تقني متعلق بجافاسكربت و React وتطوير الويب

الخلاصة التقنية

معظم أخطاء React الشائعة لا ترتبط بصعوبة المكتبة نفسها، بل بسوء فهم دورة حياة المكوّنات، وآلية تحديث الحالة، وطريقة تعامل React مع القوائم والأحداث. كلما التزمت بقواعد Hooks، وأدرت الحالة من مكان مناسب، وكتبت مكوّنات واضحة ذات مسؤوليات محددة، حصلت على تطبيق أكثر استقراراً وأسهل في التوسع والصيانة. الاهتمام بهذه التفاصيل الصغيرة يصنع فرقاً كبيراً في جودة المشروع النهائي.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *