React.Component — کلاس پایه برای ایجاد کامپوننتها با استفاده از وراثت در React. قبل از ظهور هوکها در نسخه 16.8، کامپوننتهای کلاسی تنها راه مدیریت state و چرخه حیات بودند. طبق React, 2024، کامپوننتهای کلاسی همچنان پشتیبانی میشوند، اگرچه کامپوننتهای تابعی با هوکها برای پروژههای جدید توصیه میشوند.
نکات کلیدی
React.Component — یک کلاس انتزاعی است که متدهای داخلی برای کار با state، props و چرخه حیات کامپوننت فراهم میکند. برای ایجاد یک کامپوننت کلاسی، باید کلاسی تعریف کنید که از React.Component ارثبری کند و متد render را پیادهسازی کنید.
React.Component در اولین نسخه React (2013) ظاهر شد و به مدت پنج سال راه اصلی ایجاد کامپوننتها باقی ماند. اکوسیستم React حول کلاسها ساخته شد: کامپوننتهای مرتبه بالا (HOC)، render props، context — همه این الگوها از طریق سینتکس کلاسی پیادهسازی شدند.
با انتشار React 16.8 در سال 2019، تیم React هوکها را به عنوان جایگزینی برای کلاسها معرفی کرد. هوکها همان وظایف — state، اثرات، context — را حل میکردند، اما بدون وراثت و binding پیچیده context. React.Component کاملاً پشتیبانی میشود، اما برای پروژههای جدید رویکرد تابعی توصیه میشود.
حداقل کامپوننت کلاسی — کلاسی با تنها یک متد render که یک عنصر React برمیگرداند. render — تنها متد اجباری است. باید یک تابع خالص از this.props و this.state باشد: همان مجموعه props و state همان نتیجه را میدهد.
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
سازنده قبل از mount اجرا میشود. در آن super(props) برای ارسال 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) ممنوع است — باعث رندر مجدد نمیشود و پیشبینیپذیری را از بین میبرد. بهروزرسانی state باید از طریق this.setState انجام شود که یک شیء state جدید ایجاد میکند و رندر مجدد را آغاز میکند.
setState میتواند یک شیء یا تابع دریافت کند. فرم تابعی زمانی ترجیح داده میشود که state جدید به state قبلی وابسته باشد: this.setState(prev => ({ count: prev.count + 1 })). React میتواند چندین setState را در یک batch برای بهینهسازی عملکرد گروهبندی کند.
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، state بلافاصله بهروزرسانی نمیشود. اگر نیاز به انجام عملی پس از بهروزرسانی دارید، callback را به عنوان آرگومان دوم ارسال کنید: this.setState(newState, () => console.log(this.state)).
کامپوننتهای کلاسی متدهای از پیش تعریف شدهای دارند که React در لحظات خاصی فراخوانی میکند. Mount — constructor → render → componentDidMount. بهروزرسانی — render → componentDidUpdate. Unmount — componentWillUnmount.
| متد | فاز | کاربرد |
|---|---|---|
| constructor | Mount | مقداردهی state و binding متدها |
| render | هر بار | بازگرداندن عناصر React (اجباری) |
| componentDidMount | پس از mount | درخواستهای API، اشتراکها، تایمرها |
| componentDidUpdate | پس از بهروزرسانی | واکنش به تغییر props/state |
| 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() {
// لغو درخواست در unmount
}
render() {
return <div>{this.state.user?.name}</div>;
}
}
در JavaScript، متدهای کلاس به طور پیشفرض به نمونه (instance) متصل نیستند. اگر متد را به عنوان callback — به کنترلکننده رویداد، تایمر — ارسال کنید، this undefined (در حالت strict) یا window (بدون strict mode) خواهد بود. بدون binding، this.setState خطا میدهد.
سه روش برای binding وجود دارد: bind در سازنده، تابع پیکانی در callback، و class field با تابع پیکانی. روش اول — توصیه رسمی React: bind یک بار در سازنده، بدون ایجاد مجدد تابع در هر رندر.
// روش 1: bind در سازنده (توصیه شده)
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 field — سینتکس مدرن با binding خودکار. تابع پیکانی در ویژگی کلاس، this را از محدوده دید سازنده میگیرد. نقطه ضعف — متد روی هر نمونه ایجاد میشود، نه روی prototype، که حافظه را برای صدها کامپوننت از یک نوع افزایش میدهد.
انتخاب بین کلاس و تابع — فقط یک مسئله سینتکس نیست. کامپوننتهای تابعی با هوکها مشکلات ذاتی کلاسها را حل میکنند: تکرار منطق در متدهای مختلف چرخه حیات (componentDidMount + componentDidUpdate)، پیچیدگی با this و عدم امکان استخراج منطق مرتبط در یک بلوک قابل استفاده مجدد.
کامپوننتهای تابعی آسانتر برای تست هستند — state داخلی ندارند (که قبل از هوکها فقط در کلاسها بود) و برای بررسی callbackها نیاز به mount در DOM ندارند. React کامپوننتهای تابعی را برای همه پروژههای جدید توصیه میکند، مستندات و مثالها با آنها نوشته میشوند.
کامپوننتهای کلاسی بهترین انتخاب برای کار با کدهای قدیمی باقی میمانند. اگر پروژه قبل از 2019 شروع شده باشد، احتمالاً هزاران کامپوننت کلاسی دارد. بازنویسی همه آنها به هوک در یک اسپرینت ریسکناک است. React سازگاری معکوس را تضمین میکند: کامپوننتهای کلاسی حذف نخواهند شد.
مهاجرت تدریجی با تحلیل کامپوننت آغاز میشود. کامپوننتهای ساده بدون state (stateless) اول ترجمه میشوند — آنها به سادگی با توابع جایگزین میشوند. سپس — کامپوننتهای با یک یا دو فیلد state، جایی که useState مستقیماً جایگزین this.state و this.setState میشود.
کامپوننتهای پیچیده با متدهای چرخه حیات متعدد از طریق useEffect ترجمه میشوند. منطق از componentDidMount + componentDidUpdate به useEffectهای جداگانه با وابستگیهای مختلف تقسیم میشود. componentWillUnmount با تابع بازگشتی داخل useEffect جایگزین میشود. برای منطق state پیچیده از useReducer استفاده کنید.
ابزارهای مهاجرت خودکار — @phenomnomnominal/ts-react-class-to-hook یا اسکریپتهای codemod — میتوانند کلاسهای ساده را به طور خودکار تبدیل کنند. برای موارد پیچیده، مهاجرت کار دستی باقی میماند که نیاز به درک منطق کامپوننت اصلی دارد.
سوالات متداول
بله. super(props) props را به React.Component والد منتقل میکند. بدون این فراخوانی، this.props در داخل سازنده undefined خواهد بود. در render و متدهای چرخه حیات، props حتی بدون super نیز در دسترس هستند، اما این رفتار جانبی پیادهسازی است.
React چندین فراخوانی setState را در یک batch برای کاهش تعداد رندرهای مجدد غیرضروری گروهبندی میکند. اگر setState همگام بود، هر فراخوانی باعث رندر فوری میشد و عملکرد را در بهروزرسانیهای حجیم کاهش میداد.
خیر. هوکها فقط در کامپوننتهای تابعی کار میکنند. برای پروژههای با کامپوننتهای کلاسی، تمام الگوهای قدیمی در دسترس هستند: render props، HOC و Consumer برای context. مهاجرت به هوکها نیاز به تبدیل کلاس به تابع دارد.
React.PureComponent shouldComponentUpdate را با مقایسه سطحی (shallow) props و state پیادهسازی میکند. بر خلاف Component که همیشه در setState رندر مجدد میکند، PureComponent اگر دادهها تغییر نکرده باشند، رندر را رد میکند. این یک بهینهسازی برای کامپوننتهای بدون تودرتویی پیچیده است.
از componentDidCatch و getDerivedStateFromError استفاده کنید. componentDidCatch(error, info) خطا را ثبت میکند. getDerivedStateFromError state را برای نمایش fallback-UI بهروزرسانی میکند. این متدها فقط در کامپوننتهای کلاسی کار میکنند — توابع به یک کامپوننت wrapper ErrorBoundary نیاز دارند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید