
در React، کامپوننت ها چرخه حیاتی دارند که از مراحل مختلفی تشکیل شده است. هر فاز دارای مجموعه ای از روش های چرخه حیات است که در نقاط خاصی از چرخه عمر قطعه فراخوانی می شوند. این روش ها به شما این امکان را می دهند که رفتار جزء را کنترل کنید و اقدامات خاصی را در مراحل مختلف چرخه عمر آن انجام دهید.
چرخه عمر یک قطعه دارای سه فاز اصلی است: فاز نصب، فاز به روز رسانی و فاز نصب.
مرحله نصب زمانی شروع می شود که یک جزء برای اولین بار ایجاد شده و در DOM قرار می گیرد. مرحله به روز رسانی زمانی رخ می دهد که وضعیت یا اجزای یک جزء تغییر کند. و مرحله Unmounting زمانی اتفاق می افتد که یک جزء از DOM حذف شود.
فاز نصب قطعات
مرحله نصب به دوره ای اطلاق می شود که یک جزء در حال ایجاد و درج در DOM است.
در طول این مرحله، چندین روش چرخه حیات توسط React فراخوانی میشود تا توسعهدهنده را قادر میسازد تا کامپوننت را پیکربندی کند، هر حالت لازم یا شنونده رویداد را تنظیم کند و سایر وظایف اولیه را انجام دهد.
مرحله نصب دارای سه روش چرخه عمر اصلی است که به ترتیب نامیده می شوند:
متد چرخه حیات constructor()
متد constructor()
زمانی فراخوانی می شود که کامپوننت برای اولین بار ایجاد شود. شما از آن برای مقداردهی اولیه وضعیت کامپوننت و پیوند متدها به نمونه کامپوننت استفاده می کنید. در اینجا یک مثال است:
import React, { Component } from 'react'; class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ count: prevState.count + 1 })); } render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.handleClick}>Increment</button> </div> ); } } export default Counter;
در این مثال، متد constructor()
وضعیت اولیه کامپوننت را روی یک شی با خاصیت count
روی ۰
تنظیم می کند و متد handleClick
را به نمونه کامپوننت متصل می کند. روش handleClick
وقتی روی دکمه کلیک میشود، خاصیت count
state را افزایش میدهد.
روش چرخه حیات render()
متد render()
مسئول تولید نمایش DOM مجازی مؤلفه بر اساس ویژگیها و وضعیت فعلی آن است. هر زمانی که کامپوننت نیاز به رندر شدن مجدد داشته باشد، به این دلیل که اجزا یا حالت آن تغییر کرده است، یا به این دلیل که یک جزء والد دوباره رندر شده است، فراخوانی می شود.
در مثال بالا در قسمت سازنده:
render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.handleClick}>Increment</button> </div> ); } }
روش render
مقدار شمارش فعلی و یک دکمه را نمایش می دهد. هنگامی که دکمه کلیک می شود، روش handleClick
فراخوانی می شود. این یک بهروزرسانی وضعیت را راهاندازی میکند و باعث رندر مجدد میشود و تعداد بهروزرسانیشده نمایش داده میشود.
متد چرخه حیات getDerivedStateFromProps()
getDerivedStateFromProps()
یک روش چرخه حیات موجود در React 16.3 و نسخههای بعدی است که در مرحله نصب و بهروزرسانی یک جزء فراخوانی میشود.
در مرحله نصب، getDerivedStateFromProps()
بعد از سازنده و قبل از render()
فراخوانی می شود. این روش برای هر چرخه رندر فراخوانی می شود و فرصتی را برای به روز رسانی وضعیت کامپوننت بر اساس تغییرات در props قبل از رندر اولیه فراهم می کند.
امضای getDerivedStateFromProps()
به شرح زیر است:
static getDerivedStateFromProps(props, state)
دو پارامتر نیاز دارد:
props
: لوازم به روز شده برای کامپوننت.
state
: وضعیت فعلی جزء.
متد باید شیئی را برگرداند که نشان دهنده وضعیت به روز شده مولفه است، یا اگر به روز رسانی حالت لازم نباشد، null
باشد.
مهم است که توجه داشته باشید که getDerivedStateFromProps()
یک متد ثابت است، به این معنی که به this
کلمه کلیدی دسترسی ندارد و نمی تواند با متدها یا ویژگی های نمونه جزء تعامل داشته باشد.
import React from 'react'; import ReactDOM from 'react-dom'; class Header extends React.Component { constructor(props) { super(props); this.state = {favoritefood: "rice"}; } componentDidMount() { setTimeout(() => { this.setState({favoritefood: "pizza"}) }, 1000) } static getDerivedStateFromProps(props, state) { return {favoritefood: props.favfod }; } render() { return ( <h1>My Favorite Food is {this.state.favoritefood}</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
این یک کامپوننت React به نام Header است که یک عنصر <h1>
را با رشته ای ارائه می کند که شامل مقدار this.state.favoritefood
است.
این جزء سازنده ای دارد که حالت اولیه favoritefood
را روی "برنج" تنظیم می کند.
متد componentDidMount()
نیز تعریف شده است که زمانی فراخوانی می شود که کامپوننت در DOM نصب شود. در این روش، یک تابع setTimeout()
وجود دارد که بعد از ۱ ثانیه (۱۰۰۰ میلی ثانیه) وضعیت favoritefood
را به "پیتزا" به روز می کند.
این کامپوننت همچنین دارای یک متد استاتیک getDerivedStateFromProps()
است که props
و state
به عنوان آرگومان می گیرد و یک شی را با کلید favoritefood
و مقدار props.favfod
برمی گرداند. این روش در مرحله نصب و به روز رسانی کامپوننت نامیده می شود و برای استخراج حالت از props استفاده می شود.
در نهایت، متد render()
کامپوننت، عنصر <h1>
را با مقدار this.state.favoritefood
برمیگرداند. وقتی کامپوننت با استفاده از ReactDOM.render()
رندر میشود، با شناسه "root" روی عنصر سوار میشود.
متد چرخه حیات componentDidMount()
متد componentDidMount()
زمانی فراخوانی می شود که کامپوننت در DOM سوار شود. معمولاً برای تنظیم هر شنونده یا تایمر رویداد ضروری، انجام هر تماس ضروری API یا واکشی دادهها، و انجام سایر کارهای اولیه که نیاز به دسترسی به DOM API مرورگر دارند، استفاده میشود.
در اینجا یک مثال است:
import React from 'react'; import ReactDOM from 'react-dom'; class Header extends React.Component { constructor(props) { super(props); this.state = {favoritefood: "rice"}; } componentDidMount() { setTimeout(() => { this.setState({favoritefood: "pizza"}) }, 1000) } render() { return ( <h1>My Favorite Food is {this.state.favoritefood}</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
این کد یک جزء React به نام Header
را تعریف می کند که کلاس React.Component
را گسترش می دهد. کامپوننت سازنده ای دارد که حالت جزء را با خاصیتی به نام favoritefood
در رشته «برنج» تنظیم می کند.
این کامپوننت همچنین دارای یک متد چرخه حیات componentDidMount
است که پس از نصب کامپوننت (یعنی وارد DOM) توسط React فراخوانی می شود. در این روش، یک تابع setTimeout
برای به تاخیر انداختن اجرای تابعی استفاده می شود که ویژگی حالت favoritefood
را به "پیتزا" به مدت ۱ ثانیه به روز می کند.
در نهایت، کامپوننت دارای یک متد render
است که عبارت JSX حاوی عنصر h1
را با متن "My Favorite Food is" و مقدار فعلی ویژگی حالت favoritefood
برمی گرداند.
فاز به روز رسانی کامپوننت
این مرحله زمانی اتفاق میافتد که ویژگی یا حالت یک مؤلفه تغییر میکند و مؤلفه باید در DOM بهروزرسانی شود.
متد چرخه حیات shouldComponentUpdate()
متد shouldComponentUpdate()
قبل از به روز رسانی یک جزء فراخوانی می شود. دو آرگومان نیاز دارد: nextProps
و nextState
. این متد یک مقدار بولی برمی گرداند که تعیین می کند آیا جزء باید به روز شود یا نه. اگر این متد true را برگرداند، کامپوننت به روز می شود و اگر false برگرداند، کامپوننت به روز نمی شود.
در اینجا مثالی از نحوه استفاده از shouldComponentUpdate()
آورده شده است:
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class Header extends Component { constructor(props) { super(props); this.state = { favoriteFood: 'rice' }; } shouldComponentUpdate(nextProps, nextState) { // Only re-render if the favoriteFood state has changed return this.state.favoriteFood !== nextState.favoriteFood; } changeFood = () => { this.setState({ favoriteFood: 'Pizza' }); } render() { return ( <div> <h1>My Favorite Food is {this.state.favoriteFood}</h1> <button type="button" onClick={this.changeFood}>Change food</button> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
کد بالا یک کامپوننت Header
را تعریف می کند که غذای مورد علاقه کاربر را نمایش می دهد و به کاربر اجازه می دهد با کلیک روی یک دکمه آن را تغییر دهد. متد shouldComponentUpdate()
پیادهسازی میشود تا فقط در صورتی که حالت favoriteFood
تغییر کرده باشد، کامپوننت را دوباره رندر کند، که راه خوبی برای بهینهسازی عملکرد است.
کد از دستور ES6 برای تعریف کلاس کامپوننت و متدهای آن استفاده می کند و Component
از React
برای ایجاد کلاس وارد می کند. تابع ReactDOM.render()
برای رندر مولفه Header به DOM استفاده می شود.
متد چرخه حیات componentWillUpdate()
componentWillUpdate()
یک متد چرخه حیات در React است که درست قبل از شروع چرخه بهروزرسانی یک جزء فراخوانی میشود. پروپ و حالت بعدی را به عنوان آرگومان دریافت می کند و به شما امکان می دهد قبل از به روز رسانی کامپوننت، هر گونه اقدام لازم را انجام دهید.
اما این روش برای به روز رسانی حالت توصیه نمی شود، زیرا می تواند باعث ایجاد یک حلقه بی نهایت از رندر شود. در درجه اول برای کارهایی مانند برقراری تماس های API، به روز رسانی DOM یا آماده سازی کامپوننت برای دریافت داده های جدید استفاده می شود. componentWillUpdate()
اغلب همراه با componentDidUpdate()
برای مدیریت به روز رسانی کامپوننت استفاده می شود.
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class MyComponent extends Component { state = { count: 0, }; handleClick = () => { this.setState({ count: this.state.count + 1 }); }; componentWillUpdate(nextProps, nextState) { if (nextState.count !== this.state.count) { console.log(`Count is about to update from ${this.state.count} to ${nextState.count}.`); } } render() { return ( <div> <h1>Count: {this.state.count}</h1> <button type="button" onClick={this.handleClick}> Increment </button> </div> ); } } const rootElement = document.getElementById('root'); ReactDOM.render(<MyComponent />, rootElement);
در این مثال، هر زمان که کامپوننت در شرف بهروزرسانی باشد، متد componentWillUpdate
فراخوانی میشود. در این روش می توانیم به آرگومان های nextProps
و nextState
دسترسی داشته باشیم تا تحلیل کنیم که آیا تغییراتی در وضعیت یا props کامپوننت وجود دارد یا خیر. اگر تغییراتی وجود داشته باشد، میتوانیم برخی از اقدامات یا پیامهای گزارش را قبل از بهروزرسانی انجام دهیم.
روش چرخه حیات componentDidUpdate
متد componentDidUpdate()
یک متد چرخه حیات در React است که پس از بهروزرسانی یک کامپوننت و رندر مجدد آن فراخوانی میشود. برای انجام عوارض جانبی یا عملیات اضافی هنگامی که قسمت یا وضعیت قطعه تغییر کرده است مفید است.
در اینجا مثالی از نحوه استفاده از متد componentDidUpdate()
آورده شده است:
import React, { Component } from 'react'; class ExampleComponent extends Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidUpdate(prevProps, prevState) { if (prevState.count !== this.state.count) { console.log('Count has been updated:', this.state.count); } } handleClick() { this.setState(prevState => ({ count: prevState.count + 1 })); } render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={() => this.handleClick()}>Increment</button> </div> ); } } export default ExampleComponent;
در این مثال، از متد componentDidUpdate()
برای ثبت یک پیام به کنسول هر زمان که وضعیت count
بهروزرسانی شد استفاده میشود. وضعیت قبلی ( prevState.count
) را با وضعیت فعلی ( this.state.count
) مقایسه می کند تا تحلیل کند که آیا تغییری وجود دارد یا خیر.
هر زمان که متد handleClick()
فراخوانی شود، وضعیت count
افزایش مییابد و باعث ایجاد رندر مجدد مولفه میشود. پس از رندر مجدد، componentDidUpdate()
فراخوانی می شود و مقدار به روز شده تعداد را در کنسول ثبت می کند.
مهم است که یک تحلیل شرطی در داخل componentDidUpdate()
قرار دهید تا از حلقه های بی نهایت جلوگیری کنید. اگر میخواهید وضعیت را بر اساس تغییر پایه بهروزرسانی کنید، قبل از بهروزرسانی وضعیت، حتماً پایه قبلی ( prevProps
) را با پایه فعلی ( this.props
) مقایسه کنید.
به یاد داشته باشید که componentDidUpdate()
در طول رندر اولیه کامپوننت فراخوانی نمی شود، فقط در به روز رسانی های بعدی.
از React 16.3، متد componentDidUpdate()
می تواند دو آرگومان اضافی دریافت کند: prevProps
و prevState
. این آرگومانها دسترسی به props و مقادیر حالت قبلی را فراهم میکنند که میتواند برای انجام مقایسهها مفید باشد.
اما اگر از نسخه جدیدتر React استفاده می کنید، می توانید از قلاب useEffect()
با آرایه وابستگی برای دستیابی به عملکرد مشابه استفاده کنید.
روش چرخه حیات getSnapshotBeforeUpdate
متد getSnapshotBeforeUpdate()
درست قبل از بهروزرسانی رابط کاربری مؤلفه فراخوانی میشود. این به مؤلفه اجازه می دهد تا برخی از اطلاعات را در مورد وضعیت فعلی UI، مانند موقعیت اسکرول قبل از تغییر، بگیرد. این متد مقداری را برمی گرداند که به عنوان پارامتر سوم به متد componentDidUpdate()
ارسال می شود.
در اینجا مثالی از نحوه استفاده از getSnapshotBeforeUpdate()
برای گرفتن موقعیت اسکرول یک مؤلفه قبل از به روز رسانی آورده شده است:
import React from 'react'; import ReactDOM from 'react-dom'; class Header extends React.Component { constructor(props) { super(props); this.state = {favoritefood: "rice"}; } componentDidMount() { setTimeout(() => { this.setState({favoritefood: "pizza"}) }, 1000) } getSnapshotBeforeUpdate(prevProps, prevState) { document.getElementById("div1").innerHTML = "Before the update, the favorite was " + prevState.favoritefood; } componentDidUpdate() { document.getElementById("div2").innerHTML = "The updated favorite food is " + this.state.favoritefood; } render() { return ( <div> <h1>My Favorite Food is {this.state.favoritefood}</h1> <div id="div1"></div> <div id="div2"></div> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
این یک کامپوننت React به نام Header
است که یک عنوان و دکمه ای را ارائه می دهد که با کلیک کردن، غذای مورد علاقه کاربر را نشان می دهد. این کامپوننت همچنین حالتی دارد که غذای مورد علاقه و نمایش یا عدم نمایش آن را پیگیری می کند.
متد constructor
حالت اولیه جزء شامل غذای مورد علاقه پیشفرض "برنج" و متغیر حالت showFavFood
را روی false
تنظیم میکند.
متد componentDidMount
پس از نصب کامپوننت در DOM فراخوانی می شود. در این حالت، یک تایم اوت تعیین می کند که پس از یک ثانیه غذای مورد علاقه را به «پیتزا» تغییر می دهد.
متد getSnapshotBeforeUpdate
درست قبل از به روز رسانی کامپوننت فراخوانی می شود. تحلیل میکند که آیا متغیر حالت favoriteFood
از آخرین بهروزرسانی تغییر کرده است یا خیر و در صورت تغییر، یک شی را با غذای مورد علاقه قبلی برمیگرداند. در غیر این صورت، null
برمی گرداند.
متد componentDidUpdate
پس از به روز رسانی کامپوننت فراخوانی می شود. پروپوزال، حالت و عکس فوری قبلی را به عنوان آرگومان دریافت می کند. در این حالت تحلیل میکند که آیا عکس فوری خالی نیست و غذای مورد علاقه قبلی را در کنسول ثبت میکند.
در روش render
، کامپوننت عنوانی را ارائه می دهد که متغیر حالت غذای مورد علاقه فعلی را نمایش می دهد. وقتی روی دکمه کلیک میشود، متغیر حالت showFavFood روی true
تنظیم میشود و پاراگرافای ارائه میشود که متغیر حالت غذای مورد علاقه فعلی را نشان میدهد.
در نهایت، تابع ReactDOM.render
فراخوانی می شود تا کامپوننت Header را در داخل یک عنصر HTML با شناسه "root" رندر کند.
فاز جدا کردن کامپوننت
مرحله unmounting به مرحله چرخه حیات اشاره دارد که یک مؤلفه از DOM (مدل شیء سند) حذف می شود و دیگر رندر یا قابل دسترسی نیست.
در طی این مرحله، React یک سری عملیات پاکسازی را انجام می دهد تا اطمینان حاصل کند که جزء و منابع مرتبط با آن به درستی دفع می شوند.
مرحله unmounting آخرین مرحله در چرخه حیات یک جزء React است و زمانی اتفاق میافتد که کامپوننت از درخت DOM حذف میشود.
این ممکن است به دلایل مختلفی اتفاق بیفتد، مانند زمانی که مؤلفه دیگر مورد نیاز نیست، مؤلفه والد مجدداً بدون گنجاندن مؤلفه فرزند ارائه می شود، یا زمانی که برنامه در حال پیمایش به صفحه یا نمای دیگری است.
متد چرخه حیات componentWillUnmount()
در طول مرحله unmounting، React متدهای چرخه حیات زیر را به ترتیب فراخوانی میکند:
componentWillUnmount()
: این متد درست قبل از حذف کامپوننت از DOM فراخوانی می شود. این به شما امکان می دهد هر گونه پاکسازی لازم را انجام دهید، مانند لغو تایمر، حذف شنوندگان رویداد، یا پاک کردن ساختارهای داده ای که در مرحله نصب تنظیم شده اند.
پس از فراخوانی componentWillUnmount()
، کامپوننت از DOM حذف می شود و تمام حالت و props آن از بین می رود.
توجه به این نکته مهم است که هنگامی که یک قطعه از سیستم خارج شد، نمی توان آن را دوباره نصب کرد. اگر لازم است کامپوننت را دوباره رندر کنید، باید یک نمونه جدید از آن ایجاد کنید.
در اینجا مثالی از نحوه استفاده از متد componentWillUnmount()
برای انجام پاکسازی آورده شده است:
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class MyComponent extends Component { state = { showChild: true, }; handleDelete = () => { this.setState({ showChild: false }); }; render() { const { showChild } = this.state; return ( <div> {showChild && <Child />} <button type="button" onClick={this.handleDelete}> Delete Header </button> </div> ); } } class Child extends Component { componentWillUnmount() { alert('The component named Child is about to be unmounted.'); } render() { return <h1>Hello World!</h1>; } } const rootElement = document.getElementById('root'); ReactDOM.render(<MyComponent />, rootElement);
این یک مؤلفه React است که یک MyComponent
با یک مؤلفه Child
ارائه می کند که به صورت مشروط بر اساس مقدار حالت showChild
ارائه می شود.
هنگامی که کاربر روی دکمه "Delete Header" کلیک می کند، تابع handleDelete
فراخوانی می شود که وضعیت showChild
را به false
به روز می کند. این باعث می شود کامپوننت Child
خارج شود و متد چرخه حیات componentWillUnmount
را راه اندازی کند که یک پیام هشدار نمایش می دهد.
کلاس MyComponent
کلاس Component
ارائه شده توسط React را گسترش می دهد و متغیر حالت showChild
با مقدار اولیه true
تعریف می کند. همچنین یک تابع handleDelete
تعریف می کند که وقتی کاربر روی دکمه "Delete Header" کلیک می کند، فراخوانی می شود. این تابع حالت showChild
را به false
به روز می کند.
در روش رندر MyComponent
، حالت showChild
برای رندر مشروط جزء Child
با استفاده از عملگر &&
منطقی استفاده می شود. اگر showChild
true
باشد، مؤلفه Child
ارائه خواهد شد. در غیر این صورت رندر نمی شود.
کلاس Child
کلاس Component
را گسترش میدهد و یک متد componentWillUnmount
را تعریف میکند که درست قبل از خارج شدن کامپوننت فراخوانی میشود. در این حالت پیغام هشدار نمایش داده می شود.
در نهایت، متد ReactDOM.render
فراخوانی می شود تا مؤلفه MyComponent
را در داخل عنصر با شناسه "ریشه" در سند HTML رندر کند.
نتیجه
به طور خلاصه، اجزای React دارای یک چرخه عمر متشکل از سه مرحله هستند: Mounting، Updating و Unmounting. هر فاز دارای روش های چرخه حیات خاصی است که در نقاط مختلف چرخه عمر قطعه فراخوانی می شوند.
درک این روشهای چرخه حیات میتواند به توسعهدهندگان کمک کند تا رفتار جزء را کنترل کرده و اقدامات خاصی را در مراحل مختلف چرخه عمر آن انجام دهند.