في React، كل مكون Component يمر بعدة مراحل منذ لحظة إنشائه وحتى إزالته من الصفحة. هذه المراحل تُعرف باسم Lifecycle أو دورة حياة المكون.
فهم دورة حياة المكونات في React من الأمور المهمة جدًا، لأنها تساعدك على معرفة الوقت المناسب لتنفيذ الكود، مثل جلب البيانات عند تحميل الصفحة، أو تحديث الواجهة عند تغير البيانات، أو تنظيف الموارد عند إزالة المكون من الصفحة.
ما هي Lifecycle في React؟
الـ Lifecycle أو دورة الحياة هي المراحل التي يمر بها المكون منذ إنشائه، ثم ظهوره داخل الصفحة، ثم تحديثه عند تغير البيانات، وأخيرًا إزالته من الصفحة.
بمعنى أبسط، أي Component في React يمر بثلاث مراحل رئيسية:
- Mounting: مرحلة الإنشاء والظهور في الصفحة.
- Updating: مرحلة التحديث عند تغير البيانات.
- Unmounting: مرحلة الإزالة من الصفحة.
أهمية Lifecycle في React
تساعدك دورة الحياة في React على التحكم في توقيت تنفيذ الكود داخل المكون. فبدلًا من تنفيذ الكود بشكل عشوائي، يمكنك تحديد متى يتم تنفيذ كل جزء من الكود بناءً على المرحلة التي يمر بها المكون.
على سبيل المثال، يمكنك جلب البيانات من API عند تحميل المكون لأول مرة، أو تحديث عنوان الصفحة عند تغير قيمة معينة، أو إيقاف مؤقت Timer عند حذف المكون من الصفحة.
دورة الحياة في React تساعدك على
- تنفيذ الكود في الوقت المناسب.
- جلب البيانات عند تحميل الصفحة.
- تحديث الواجهة عند تغيير البيانات.
- تنظيف الموارد عند إغلاق أو حذف المكون.
- تنظيم الكود داخل المكونات بشكل أفضل.
مراحل دورة الحياة في React
تمر دورة حياة المكون في React بثلاث مراحل أساسية. كل مرحلة لها استخدام معين، وفي Class Components كانت هناك دوال خاصة بكل مرحلة، أما في Functional Components فيتم غالبًا استخدام useEffect بدلًا منها.
Mounting مرحلة الإنشاء
مرحلة Mounting هي المرحلة التي يتم فيها إنشاء المكون لأول مرة، ثم إضافته إلى الصفحة داخل DOM.
بمعنى آخر، هذه المرحلة تحدث عند ظهور المكون لأول مرة أمام المستخدم.
في Class Components نستخدم الدالة componentDidMount() لتنفيذ كود بعد ظهور المكون في الصفحة.
componentDidMount() {
console.log("Component mounted");
}هذه الدالة تعمل مرة واحدة فقط بعد تحميل المكون، لذلك تُستخدم غالبًا في جلب البيانات من API أو تنفيذ كود نحتاجه مرة واحدة فقط.
بديل componentDidMount باستخدام useEffect
في Functional Components يمكننا استخدام useEffect بدلًا من componentDidMount.
عند وضع مصفوفة فارغة [] في نهاية useEffect، فهذا يعني أن الكود سيتم تنفيذه مرة واحدة فقط عند تحميل المكون.
useEffect(() => {
console.log("Component mounted");
}, []); وجود [] هنا مهم جدًا، لأنه يخبر React أن هذا التأثير لا يعتمد على أي قيمة متغيرة، لذلك يتم تشغيله مرة واحدة فقط.
Updating مرحلة التحديث
مرحلة Updating تحدث عندما تتغير بيانات داخل المكون، مثل state أو props.
عند تغير هذه البيانات، تقوم React بإعادة عرض المكون من جديد حتى تظهر التغييرات في الواجهة.
في Class Components نستخدم الدالة componentDidUpdate() لتنفيذ كود بعد حدوث التحديث.
componentDidUpdate() {
document.title = `Count: ${this.state.count}`;
} في هذا المثال، عند تغير قيمة count يتم تحديث عنوان الصفحة باستخدام القيمة الجديدة.
بديل componentDidUpdate باستخدام useEffect
في Functional Components يمكننا استخدام useEffect مع وضع المتغير داخل مصفوفة الاعتماديات.
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]); وجود count داخل المصفوفة يعني أن الكود الموجود داخل useEffect سيتم تنفيذه فقط عندما تتغير قيمة count.
هذه الطريقة مفيدة جدًا عندما تريد تنفيذ كود معين بناءً على تغير قيمة محددة داخل المكون.
Unmounting مرحلة الإزالة
مرحلة Unmounting تحدث عندما يتم حذف المكون من الصفحة أو لم يعد موجودًا داخل DOM.
في هذه المرحلة نحتاج أحيانًا إلى تنظيف بعض الموارد، مثل إيقاف Timer أو إلغاء اشتراك أو إزالة Event Listener.
في Class Components نستخدم الدالة componentWillUnmount() لتنفيذ كود قبل إزالة المكون.
componentWillUnmount() {
console.log("Component will unmount");
}بديل componentWillUnmount باستخدام useEffect
في Functional Components يمكن تنفيذ كود الإزالة من خلال كتابة دالة return داخل useEffect.
useEffect(() => {
return () => {
console.log("Component will unmount");
};
}, []); الكود الموجود داخل return يسمى Cleanup Function، ويتم تنفيذه عند إزالة المكون من الصفحة.
هذه الطريقة مهمة جدًا في الحالات التي تحتاج فيها إلى تنظيف أي شيء تم تشغيله أثناء وجود المكون.
مقارنة بين Class Components و useEffect
في السابق، كانت دورة حياة المكونات تعتمد بشكل كبير على Class Components، وكان لكل مرحلة دالة خاصة بها.
أما في React الحديثة، فأصبح من الشائع استخدام Functional Components مع useEffect لتنفيذ نفس الفكرة بطريقة أبسط وأكثر تنظيمًا.
| المرحلة | Class Component | Functional Component |
|---|---|---|
| Mounting | componentDidMount | useEffect(() => {}, []) |
| Updating | componentDidUpdate | useEffect(() => {}, [value]) |
| Unmounting | componentWillUnmount | return داخل useEffect |
كود كامل باستخدام Class Component
في المثال التالي سنقوم بإنشاء عداد بسيط باستخدام Class Component. يحتوي هذا المكون على قيمة count داخل state، وزرين لزيادة أو تقليل الرقم.
كما نستخدم دوال Lifecycle مثل componentDidMount و componentDidUpdate و componentWillUnmount.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
}
componentDidMount() {
console.log("Component mounted");
}
componentDidUpdate() {
document.title = `Count: ${this.state.count}`;
}
componentWillUnmount() {
console.log("Component will unmount");
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
decrement = () => {
this.setState({
count: this.state.count == 0 ? 0 : this.state.count - 1
});
}
render() {
return (
<div>
<h3>Counter: {this.state.count}</h3>
<button
style={{ marginRight: '10px' }}
onClick={this.increment}
>
Increment
</button>
<button onClick={this.decrement}>
Decrement
</button>
</div>
);
}
}
export default Counter;شرح الكود الكامل
في بداية الكود أنشأنا Class Component باسم Counter يرث من React.Component.
class Counter extends React.Component بعد ذلك استخدمنا constructor لتعريف الحالة الابتدائية للمكون. الحالة تحتوي على قيمة واحدة وهي count وتبدأ من الرقم صفر.
this.state = {
count: 0
}; ثم قمنا بربط الدوال increment و decrement باستخدام bind حتى نستطيع استخدام this داخل هذه الدوال.
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);شرح componentDidMount
الدالة componentDidMount يتم تنفيذها بعد ظهور المكون في الصفحة لأول مرة.
componentDidMount() {
console.log("Component mounted");
}في هذا المثال قمنا بطباعة رسالة داخل Console عند تحميل المكون. وفي التطبيقات الحقيقية يمكن استخدام هذه الدالة لجلب البيانات من API.
شرح componentDidUpdate
الدالة componentDidUpdate يتم تنفيذها بعد تحديث المكون، أي بعد تغير state أو props.
componentDidUpdate() {
document.title = `Count: ${this.state.count}`;
} في هذا المثال قمنا بتحديث عنوان الصفحة حسب قيمة العداد الحالية. كلما تغيرت قيمة count سيتم تنفيذ هذه الدالة وتحديث document.title.
شرح componentWillUnmount
الدالة componentWillUnmount يتم تنفيذها قبل إزالة المكون من الصفحة.
componentWillUnmount() {
console.log("Component will unmount");
}هذه الدالة مفيدة جدًا عندما تحتاج إلى تنظيف موارد معينة قبل حذف المكون، مثل إيقاف مؤقت أو إلغاء اشتراك أو إزالة حدث.
شرح دالة increment
دالة increment مسؤولة عن زيادة قيمة العداد بمقدار واحد في كل مرة يضغط فيها المستخدم على زر الزيادة.
increment = () => {
this.setState({ count: this.state.count + 1 });
} نستخدم setState لتحديث قيمة count داخل الحالة، وبعد التحديث تقوم React بإعادة عرض المكون بالقيمة الجديدة.
شرح دالة decrement
دالة decrement مسؤولة عن تقليل قيمة العداد بمقدار واحد، لكنها تمنع القيمة من النزول أقل من صفر.
decrement = () => {
this.setState({
count: this.state.count == 0 ? 0 : this.state.count - 1
});
} هنا استخدمنا شرطًا بسيطًا. إذا كانت قيمة count تساوي صفر، ستبقى صفر. أما إذا كانت أكبر من صفر، سيتم إنقاصها بمقدار واحد.
كود كامل باستخدام Functional Component و useEffect
يمكن تنفيذ نفس فكرة العداد باستخدام Functional Component و useEffect بدلًا من Class Component.
import { useEffect, useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Component mounted");
return () => {
console.log("Component will unmount");
};
}, []);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count == 0 ? 0 : count - 1);
};
return (
<div>
<h3>Counter: {count}</h3>
<button
style={{ marginRight: '10px' }}
onClick={increment}
>
Increment
</button>
<button onClick={decrement}>
Decrement
</button>
</div>
);
}
export default Counter;شرح نسخة Functional Component
في هذه النسخة استخدمنا useState لإنشاء حالة باسم count بدلًا من استخدام this.state.
const [count, setCount] = useState(0); ثم استخدمنا أول useEffect لمحاكاة مرحلتي Mounting و Unmounting.
useEffect(() => {
console.log("Component mounted");
return () => {
console.log("Component will unmount");
};
}, []); الكود الموجود قبل return يعمل عند تحميل المكون، أما الكود الموجود داخل return فيعمل عند إزالة المكون.
بعد ذلك استخدمنا useEffect آخر لمراقبة تغير قيمة count.
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);هذا يعني أن عنوان الصفحة سيتم تحديثه فقط عند تغير قيمة العداد.
الفرق بين [] و [count] في useEffect
من أهم الأمور التي يجب فهمها عند استخدام useEffect هي مصفوفة الاعتماديات.
[]: تعني أن الكود يعمل مرة واحدة فقط عند تحميل المكون.[count]: تعني أن الكود يعمل عند تحميل المكون، ثم يعمل مرة أخرى عند تغير قيمةcount.- بدون مصفوفة: يعمل الكود بعد كل عملية Render، وهذا قد يسبب مشاكل في الأداء إذا لم تكن تحتاجه.
متى نستخدم Lifecycle؟
نستخدم دورة حياة المكونات عندما نحتاج إلى تنفيذ كود في وقت معين داخل المكون.
من أشهر الاستخدامات:
- جلب البيانات من API عند تحميل الصفحة.
- تحديث عنوان الصفحة عند تغير البيانات.
- تشغيل أو إيقاف مؤقت Timer.
- إضافة أو إزالة Event Listener.
- تنظيف الاشتراكات أو الاتصالات عند حذف المكون.
الخلاصة
الـ Lifecycle في React هي المراحل التي يمر بها المكون منذ إنشائه وحتى إزالته من الصفحة. هذه المراحل تساعدك على تنفيذ الكود في الوقت المناسب والتحكم في سلوك المكون بشكل أفضل.
في Class Components نستخدم دوال مثل componentDidMount و componentDidUpdate و componentWillUnmount. أما في Functional Components فنستخدم useEffect لتنفيذ نفس الأفكار بطريقة أبسط وأكثر استخدامًا في React الحديثة.
بشكل عام، فهم Lifecycle و useEffect يساعدك على بناء مكونات أكثر تنظيمًا، ويجعلك قادرًا على التعامل مع البيانات والتحديثات وتنظيف الموارد بطريقة صحيحة داخل تطبيقات React.
مزيد من المقالات : خصائص TextFormField تحسن من عمليات ادخال البيانات لدى المستخدمين في Flutter






