React.Component — المكونات الصفية وكيف تعمل

المؤلف: IT Sectr نُشر: 2026-07-04 وقت القراءة: 9 دق

React.Component هو الصنف الأساسي لإنشاء المكونات باستخدام الوراثة في React. قبل ظهور الخطافات (hooks) في الإصدار 16.8، كانت المكونات الصفية هي الطريقة الوحيدة لإدارة الحالة ودورة الحياة. وفقًا React، 2024، المكونات الصفية لا تزال مدعومة، على الرغم من أن المكونات الدالية مع الخطافات موصى بها للمشاريع الجديدة.

الخلاصة

  • React.Component هو الصنف الأساسي الذي ترث منه المكونات الصفية عبر extends Component.
  • الحالة تُدار عبر this.state وتُحدَّث فقط عبر this.setState — الطفرات المباشرة محظورة.
  • دورة الحياة تتضمن الطرق componentDidMount و componentDidUpdate و componentWillUnmount.
  • this في طرق الصنف يتطلب ربط السياق — عبر bind أو الدوال السهمية أو class fields.
  • الترحيل إلى المكونات الدالية ممكن تدريجيًا: الخطافات والصفوف يمكن أن تتعايش في نفس المشروع.

ما هو React.Component؟

React.Component هو صنف مجرد يوفر طرقًا مدمجة للعمل مع الحالة والخواص ودورة حياة المكون. لإنشاء مكون صفي، عليك تعريف صنف يرث من React.Component وتنفيذ طريقة render.

ظهر React.Component في أول إصدار من React (2013) وظل الطريقة الرئيسية لإنشاء المكونات لمدة خمس سنوات. بُني نظام React البيئي حول الصفوف: المكونات عالية المستوى (HOC)، render props، السياق — كل هذه الأنماط نُفِّذَت باستخدام صيغة الصفوف.

مع إصدار React 16.8 في 2019، قدم فريق React الخطافات كبديل للصفوف. حلت الخطافات نفس المشاكل — الحالة، التأثيرات، السياق — لكن بدون وراثة وربط سياق معقد. React.Component لا يزال مدعومًا بالكامل، لكن النهج الدالي موصى به للمشاريع الجديدة.

إنشاء مكون صفي

أبسط مكون صفي هو صنف بطريقة واحدة هي render التي تعيد عنصر React. render هي الطريقة الإلزامية الوحيدة. يجب أن تكون دالة نقية من this.props و this.state: نفس مجموعة الخواص والحالة تعطي نفس النتيجة.

js
import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

الباني وتهيئة الحالة

يُنفَّذ الباني قبل التثبيت. يستدعي super(props) لتمرير الخواص إلى الصنف الأب ويُهيِّئ this.state. لا يُوصى باستخدام الباني لأغراض أخرى — الاشتراكات، استدعاءات API — لذلك يوجد componentDidMount.

js
class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  render() {
    return <p>Count: {this.state.count}</p>;
  }
}

إدارة الحالة عبر this.state و this.setState

this.state هو كائن يحتوي على بيانات المكون. تغييره مباشرة (this.state.count = 1) محظور — لا يسبب إعادة تصيير ويكسر قابلية التوقع. يجب تحديث الحالة عبر this.setState الذي ينشئ كائن حالة جديد ويطلق إعادة التصيير.

يمكن لـ setState أن يقبل كائنًا أو دالة. الصيغة الدالية مفضلة عندما تعتمد الحالة الجديدة على السابقة: this.setState(prev => ({ count: prev.count + 1 })). يمكن لـ React تجميع عدة استدعاءات setState في دفعة واحدة لتحسين الأداء.

js
class Toggle extends Component {
  constructor(props) {
    super(props);
    this.state = { isOn: false };
  }

  handleClick() {
    this.setState(prev => ({ isOn: !prev.isOn }));
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}>
        {this.state.isOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

خاصية مهمة لـ setState هي أنه غير متزامن. بعد استدعاء setState، لا تتحدَّث الحالة فورًا. إذا كنت بحاجة لتنفيذ إجراء بعد التحديث، مرر دالة رد كوسيط ثانٍ: this.setState(newState, () => console.log(this.state)).

طرق دورة الحياة

المكونات الصفية لها طرق محددة مسبقًا يستدعيها React في لحظات معينة. التثبيت — constructor → render → componentDidMount. التحديث — render → componentDidUpdate. إلغاء التثبيت — componentWillUnmount.

الطريقةالمرحلةالغرض
constructorالتثبيتتهيئة الحالة وربط الطرق
renderكل مرةإرجاع عناصر React (إلزامي)
componentDidMountبعد التثبيتطلبات API، الاشتراكات، المؤقتات
componentDidUpdateبعد التحديثالتفاعل مع تغييرات الخواص/الحالة
componentWillUnmountقبل الإزالةتنظيف الاشتراكات والمؤقتات وأحداث المستمع

ComponentDidMount — جلب البيانات

componentDidMount هو المكان الرئيسي لـالتأثيرات الجانبية بعد أول تصيير. هنا تُنفَّذ طلبات HTTP، وتُقام اتصالات WebSocket، وتُبدَأ المؤقتات. إذا لم تنظف الاشتراك في componentWillUnmount، يحدث تسرب للذاكرة.

js
class UserProfile extends Component {
  componentDidMount() {
    fetch(`/api/users/${this.props.userId}`)
      .then(res => res.json())
      .then(data => this.setState({ user: data }));
  }

  componentWillUnmount() {
    // Cancel request on unmount
  }

  render() {
    return <div>{this.state.user?.name}</div>;
  }
}

ربط سياق this في الطرق

في JavaScript، طرق الصفوف غير مرتبطة بالمثيل افتراضيًا. إذا مررت طريقة كدالة رد — لمعالج حدث، لمؤقت — سيكون this غير معرف (في الوضع الصارم) أو window (بدون وضع صارم). بدون ربط، this.setState سيُخطئ.

هناك ثلاث طرق للربط: bind في الباني، دالة سهمية في رد النداء، و class field مع دالة سهمية. الطريقة الأولى هي التوصية الرسمية من React: ربط مرة واحدة في الباني، دون إعادة إنشاء الدالة في كل تصيير.

js
// Method 1: bind in constructor (recommended)
class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ clicked: true });
  }

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

Class fields — صيغة حديثة مع ربط تلقائي. دالة سهمية في خاصية صنف تلتقط this من نطاق الباني. العيب هو أن الطريقة تُنشأ في كل مثيل، وليس على النموذج الأولي، مما يزيد استخدام الذاكرة لمئات المكونات من نفس النوع.

المقارنة بين المكونات الصفية والدالية

الاختيار بين الصف والدالة ليس مجرد مسألة صيغة. المكونات الدالية مع الخطافات تحل مشاكل متأصلة في الصفوف: تكرار المنطق في طرق دورة حياة مختلفة (componentDidMount + componentDidUpdate)، التعقيد مع this، وعدم القدرة على استخراج منطق ذي صلة في كتلة قابلة لإعادة الاستخدام.

المكونات الدالية أسهل في الاختبار — ليس لديها حالة داخلية (التي قبل الخطافات كانت متاحة فقط في الصفوف) ولا تتطلب تثبيتًا في DOM للتحقق من دوال الرد. يوصي React بالمكونات الدالية لجميع المشاريع الجديدة؛ التوثيق والأمثلة تُكتب بها.

المكونات الصفية تبقى الخيار الأفضل عند العمل مع الكود القديم. إذا بدأ المشروع قبل 2019، فمن المحتمل أنه يحتوي على آلاف المكونات الصفية. إعادة كتابتها كلها إلى خطافات في سباق واحد محفوف بالمخاطر. React يضمن التوافق العكسي: المكونات الصفية لن تُحذف.

استراتيجية الترحيل من الصفوف إلى الخطافات

يبدأ الترحيل التدريجي بتحليل المكون. المكونات البسيطة بدون حالة تُرحَّل أولاً — تُستبدل بوظائف ببساطة. ثم — المكونات التي تحتوي على حقل أو اثنين من الحالة، حيث يستبدل useState مباشرة this.state و this.setState.

المكونات المعقدة ذات طرق دورة حياة متعددة تُرحَّل عبر useEffect. يُقسَّم المنطق من componentDidMount + componentDidUpdate إلى استدعاءات منفصلة لـ useEffect باعتمادات مختلفة. يُستبدل componentWillUnmount بدالة إرجاع داخل useEffect. للمنطق المعقد للحالة، استخدم useReducer.

أدوات الترحيل الآلي — @phenomnomnominal/ts-react-class-to-hook أو نصوص codemod — يمكنها تحويل الصفوف البسيطة تلقائيًا. للحالات المعقدة، يبقى الترحيل عملاً يدويًا يتطلب فهم منطق المكون الأصلي.

الأسئلة الشائعة

هل استدعاء super(props) إلزامي في الباني؟

نعم. super(props) يمرر الخواص إلى React.Component الأب. بدون هذا الاستدعاء، سيكون this.props غير معرف داخل الباني. في render وطرق دورة الحياة، الخواص متاحة حتى بدون super، لكن هذا سلوك جانبي للتنفيذ.

لماذا setState غير متزامن؟

React يجمع عدة استدعاءات setState في دفعة واحدة لتقليل إعادة التصيير غير الضرورية. لو كان setState متزامنًا، كل استدعاء كان سيسبب تصييرًا فوريًا، مما يقلل الأداء أثناء التحديثات الجماعية.

هل يمكنني استخدام الخطافات داخل مكون صفي؟

لا. الخطافات تعمل فقط في المكونات الدالية. للمشاريع ذات المكونات الصفية، كل الأنماط القديمة متاحة: render props، HOC و Consumer للسياق. الترحيل إلى الخطافات يتطلب تحويل الصف إلى دالة.

ما هو PureComponent وما الفرق بينه وبين Component؟

React.PureComponent يطبق shouldComponentUpdate بمقارنة سطحية للخواص والحالة. على عكس Component الذي يعيد التصيير دائمًا مع setState، PureComponent يتخطى إعادة التصيير إذا لم تتغير البيانات. هذا تحسين للمكونات دون تداخل معقد.

كيف أتعامل مع خطأ في مكون صفي؟

استخدم componentDidCatch و getDerivedStateFromError. componentDidCatch(error, info) يسجل الخطأ. getDerivedStateFromError يحدِّث الحالة لعرض واجهة احتياطية. هذه الطرق تعمل فقط في المكونات الصفية — الدوال تحتاج إلى مكون ErrorBoundary مغلف.

الملخص

  • React.Component هو الصنف الأساسي للمكونات مع الوراثة والحالة وطرق دورة الحياة.
  • this.state يُهيَّأ في الباني، يُحدَّث فقط عبر this.setState — الطفرات المباشرة محظورة.
  • componentDidMount هو المكان الرئيسي لطلبات API والاشتراكات والمؤقتات بعد أول تصيير.
  • componentWillUnmount هو التنظيف الإلزامي للاشتراكات والمؤقتات لمنع تسرب الذاكرة.
  • ربط this إلزامي: bind في الباني هو الطريقة الموصى بها لطرق الاستدعاء.
  • الخطافات حلت محل المكونات الصفية للمشاريع الجديدة، لكن الصفوف تبقى مدعومة بالكامل.
  • الترحيل إلى الخطافات يتم تدريجيًا: المكونات عديمة الحالة أولاً، المعقدة عبر useReducer و useEffect.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا