React.Component هو الصنف الأساسي لإنشاء المكونات باستخدام الوراثة في React. قبل ظهور الخطافات (hooks) في الإصدار 16.8، كانت المكونات الصفية هي الطريقة الوحيدة لإدارة الحالة ودورة الحياة. وفقًا React، 2024، المكونات الصفية لا تزال مدعومة، على الرغم من أن المكونات الدالية مع الخطافات موصى بها للمشاريع الجديدة.
الخلاصة
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: نفس مجموعة الخواص والحالة تعطي نفس النتيجة.
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
يُنفَّذ الباني قبل التثبيت. يستدعي super(props) لتمرير الخواص إلى الصنف الأب ويُهيِّئ this.state. لا يُوصى باستخدام الباني لأغراض أخرى — الاشتراكات، استدعاءات API — لذلك يوجد componentDidMount.
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return <p>Count: {this.state.count}</p>;
}
}
this.state هو كائن يحتوي على بيانات المكون. تغييره مباشرة (this.state.count = 1) محظور — لا يسبب إعادة تصيير ويكسر قابلية التوقع. يجب تحديث الحالة عبر this.setState الذي ينشئ كائن حالة جديد ويطلق إعادة التصيير.
يمكن لـ setState أن يقبل كائنًا أو دالة. الصيغة الدالية مفضلة عندما تعتمد الحالة الجديدة على السابقة: this.setState(prev => ({ count: prev.count + 1 })). يمكن لـ React تجميع عدة استدعاءات setState في دفعة واحدة لتحسين الأداء.
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 هو المكان الرئيسي لـالتأثيرات الجانبية بعد أول تصيير. هنا تُنفَّذ طلبات HTTP، وتُقام اتصالات WebSocket، وتُبدَأ المؤقتات. إذا لم تنظف الاشتراك في componentWillUnmount، يحدث تسرب للذاكرة.
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>;
}
}
في JavaScript، طرق الصفوف غير مرتبطة بالمثيل افتراضيًا. إذا مررت طريقة كدالة رد — لمعالج حدث، لمؤقت — سيكون this غير معرف (في الوضع الصارم) أو window (بدون وضع صارم). بدون ربط، this.setState سيُخطئ.
هناك ثلاث طرق للربط: bind في الباني، دالة سهمية في رد النداء، و class field مع دالة سهمية. الطريقة الأولى هي التوصية الرسمية من React: ربط مرة واحدة في الباني، دون إعادة إنشاء الدالة في كل تصيير.
// 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) يمرر الخواص إلى React.Component الأب. بدون هذا الاستدعاء، سيكون this.props غير معرف داخل الباني. في render وطرق دورة الحياة، الخواص متاحة حتى بدون super، لكن هذا سلوك جانبي للتنفيذ.
React يجمع عدة استدعاءات setState في دفعة واحدة لتقليل إعادة التصيير غير الضرورية. لو كان setState متزامنًا، كل استدعاء كان سيسبب تصييرًا فوريًا، مما يقلل الأداء أثناء التحديثات الجماعية.
لا. الخطافات تعمل فقط في المكونات الدالية. للمشاريع ذات المكونات الصفية، كل الأنماط القديمة متاحة: render props، HOC و Consumer للسياق. الترحيل إلى الخطافات يتطلب تحويل الصف إلى دالة.
React.PureComponent يطبق shouldComponentUpdate بمقارنة سطحية للخواص والحالة. على عكس Component الذي يعيد التصيير دائمًا مع setState، PureComponent يتخطى إعادة التصيير إذا لم تتغير البيانات. هذا تحسين للمكونات دون تداخل معقد.
استخدم componentDidCatch و getDerivedStateFromError. componentDidCatch(error, info) يسجل الخطأ. getDerivedStateFromError يحدِّث الحالة لعرض واجهة احتياطية. هذه الطرق تعمل فقط في المكونات الصفية — الدوال تحتاج إلى مكون ErrorBoundary مغلف.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.