انواع کامپوننت ری اکت
در React، دو نوع اصلی کامپوننت وجود دارند:
- کامپوننتهای تابعی (Functional Components)
- کامپوننتهای کلاسی (Class Components)
کامپوننتهای تابعی سادهتر و مبتنی بر توابع جاوااسکریپت هستند و عموماً برای نمایش محتوای ساده و ایستا استفاده میشوند. این نوع کامپوننتها از نسخه 16.8 React و معرفی hooks، قدرتمندتر شدهاند و اکنون قابلیت مدیریت وضعیت (state) و اثرات جانبی (side effects) را دارند.
در مقابل، کامپوننتهای کلاسی بر اساس کلاسهای ES6 جاوا اسکریپت ساخته شدهاند و امکان استفاده از متدهای lifecycle را برای مدیریت وضعیت و رفتار کامپوننت فراهم میکنند. اگرچه کامپوننتهای کلاسی در پروژههای قدیمیتر رایجتر بودند، اما امروزه توسعهدهندگان بیشتر به سمت استفاده از کامپوننتهای تابعی حرکت کردهاند، زیرا سادهتر و خواناتر هستند و قابلیتهایی مشابه کامپوننتهای کلاسی ارائه میدهند.
در این مقاله از ویکس سِوِن، تفاوتهای اصلی این دو نوع کامپوننت React و موارد استفاده هر یک را بررسی خواهیم کرد تا توسعهدهندگان بتوانند بر اساس نیاز پروژههای خود، انتخاب مناسبی از انواع کامپوننت ری اکت داشته باشند.
تعریف و ساختار کامپوننت های ری اکت
کامپوننتهای تابعی
این نوع کامپوننتها در اصل توابع ساده جاوااسکریپت هستند که با استفاده از سینتکس بهینه و سادهتر نوشته میشوند و خروجی آنها JSX است. از آنجا که تابع هستند، نیازی به استفاده از کلمه کلیدی this ندارند. این ویژگی باعث میشود کد تمیزتر و قابلفهمتر باشد. پیش از معرفی Hooks در نسخه 16.8 ری اکت، این کامپوننتها تنها برای نمایش دادههای ایستا و بدون قابلیت مدیریت وضعیت یا lifecycle methods مورد استفاده قرار میگرفتند. اما اکنون، با Hooks میتوانید وضعیت (state) و متدهای lifecycle را در کامپوننتهای تابعی مدیریت کنید.
نمونهای از کامپوننت تابعی ساده
function MyComponent() {
return <h1>Hello, World!</h1>;
}
نمونهای از کامپوننت تابعی پیشرفته با استفاده از Hooks
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
کامپوننتهای کلاسی
این کامپوننتها به عنوان کلاسهای جاوا اسکریپت تعریف میشوند و از React.Component ارثبری میکنند. آنها معمولاً برای مدیریت وضعیت (state) و چرخه عمر (lifecycle methods) استفاده میشوند. در کامپوننتهای کلاسی، باید از کلمه کلیدی this برای دسترسی به وضعیت یا متدها استفاده شود، که در برخی موارد ممکن است پیچیدگیهای اضافی ایجاد کند.
نمونهای از کامپوننت کلاسی ساده
class MyComponent extends React.Component {
render() {
return <h1>Hello, World!</h1>;
}
}
نمونهای از کامپوننت کلاسی پیشرفته با وضعیت
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.increment}>Click me</button>
</div>
);
}
}
تفاوتهای کلیدی:
در میان انواع کامپوننت ری اکت، کامپوننتهای تابعی سادهتر، خواناتر، و برای استفاده در پروژههای مدرن ترجیح داده میشوند. کامپوننتهای کلاسی اگرچه همچنان پشتیبانی میشوند، اما در پروژههای جدید کمتر استفاده میشوند.
مدیریت state و lifecycle در انواع کامپوننت ری اکت
در کامپوننتهای تابعی
در گذشته، کامپوننتهای تابعی به دلیل نداشتن قابلیت داخلی برای مدیریت state و lifecycle methods، تنها برای نمایش رابط کاربری استاتیک استفاده میشدند. اما با معرفی Hooks در نسخه 16.8، این محدودیت برطرف شد. اکنون، کامپوننتهای تابعی میتوانند با استفاده از useState و useEffect، وضعیت داخلی و متدهای چرخه عمر را مدیریت کنند.
مزایای استفاده از Hooks
- useState: امکان تعریف وضعیت محلی برای یک کامپوننت بدون استفاده از کلاس.
- useEffect: جایگزینی متدهای چرخه عمر مانند componentDidMount، componentDidUpdate و componentWillUnmount برای مدیریت اثرات جانبی، مانند درخواستهای API یا تنظیم تایمرها.
نمونه استفاده از Hooks در یک کامپوننت تابعی
function Counter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log(`You clicked ${count} times`);
return () => console.log('Cleanup effect');
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
در کامپوننتهای کلاسی
کامپوننتهای کلاسی به طور ذاتی از state و متدهای lifecycle پشتیبانی میکنند. شما میتوانید با استفاده از متدهای داخلی مانند componentDidMount و componentWillUnmount، وضعیتها و اثرات جانبی را مدیریت کنید. هرچند کدنویسی با این روش میتواند پیچیدگیهایی مانند مدیریت this ایجاد کند.
نمونه مدیریت state و lifecycle در یک کامپوننت کلاسی
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
console.log(`Mounted with count: ${this.state.count}`);
}
componentDidUpdate(prevProps, prevState) {
console.log(`Updated from ${prevState.count} to ${this.state.count}`);
}
componentWillUnmount() {
console.log('Cleanup before unmounting');
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.increment}>Click me</button>
</div>
);
}
}
تفاوتهای کلیدی:
- تابعی: سادگی کد، عدم نیاز به مدیریت this، قابلیت انعطافپذیری بالا با Hooks.
- کلاسی: دسترسی پیشفرض به متدهای lifecycle و state، اما با پیچیدگی بیشتر در مدیریت this.
در پروژههای مدرن، کامپوننتهای تابعی به دلیل سینتکس سادهتر و پشتیبانی از Hooks بهطور گسترده ترجیح داده میشوند.
مقایسه سادگی و خوانایی کد در کامپوننت های ری اکتی
کامپوننتهای تابعی
- کامپوننتهای تابعی با استفاده از یک تابع ساده ساخته میشوند که مستقیماً JSX یا داده مورد نیاز را برمیگرداند. این ویژگی باعث میشود کدنویسی آنها بسیار مختصر، تمیز و خوانا باشد.
- عدم نیاز به استفاده از متدهای پیچیدهای مانند constructor یا this، خوانایی و درک کد را برای توسعهدهندگان تازهکار و حتی حرفهای آسانتر میکند.
- با معرفی Hooks، تواناییهایی مانند مدیریت وضعیت و اثرات جانبی نیز به این کامپوننتها افزوده شده است، که این موضوع جذابیت و کاربرد آنها را چندین برابر کرده است.
نمونه:
function WelcomeMessage({ name }) {
return <h1>Welcome, {name}!</h1>;
}
ویژگیهای بارز کامپوننت تابعی
- بدون نیاز به ساختار پیچیده.
- مناسب برای کامپوننتهایی که به وضعیت ساده نیاز دارند یا اصلاً از وضعیت استفاده نمیکنند.
- قابلیت گسترش با Hooks برای سناریوهای پیچیدهتر.
کامپوننتهای کلاسی
- این کامپوننتها معمولاً ساختار طولانیتری دارند و استفاده از کلاسها و متدهایی مانند render() باعث افزایش حجم کد و پیچیدگی آن میشود.
- نیاز به مدیریت this و مفهوم ارثبری میتواند در پروژههای بزرگ یا برای توسعهدهندگان مبتدی چالشبرانگیز باشد.
- با این حال، در گذشته این کامپوننتها تنها گزینه برای مدیریت وضعیت و lifecycle methods بودند.
نمونه:
class WelcomeMessage extends React.Component {
render() {
return <h1>Welcome, {this.props.name}!</h1>;
}
}
عملکرد انواع کامپوننت ری اکت
کامپوننتهای تابعی
- به دلیل ساختار سادهتر، این نوع کامپوننتها عملکرد بهتری در محیطهای پیچیدهتر دارند، زیرا فرآیندهایی مانند ارثبری از کلاس یا مدیریت this حذف شدهاند.
- در ترکیب با React.memo، کامپوننتهای تابعی میتوانند بهطور خودکار از بازپردازشهای غیرضروری جلوگیری کنند و این به بهینهسازی عملکرد کمک میکند.
- استفاده از Hooks مانند useMemo یا useCallback نیز امکان بهینهسازی بیشتر را فراهم میکند، که بهویژه در کامپوننتهایی با تعداد بالای رندرها بسیار مفید است.
کامپوننتهای کلاسی
- در گذشته، کامپوننتهای کلاسی به دلیل فرآیندهای داخلی پیچیدهتر ممکن بود تا حدودی عملکرد کمتری داشته باشند.
- عملیاتهایی مانند binding متدها به this میتواند در کامپوننتهای بزرگ یا پرکاربرد منجر به افزایش مصرف منابع شود.
- با این حال، این کامپوننتها همچنان در مواردی که نیاز به ساختارهای قدیمیتر یا پیچیدهتر باشد استفاده میشوند.
مقایسه کلی:
- تابعی: سرعت بالاتر، خوانایی بیشتر و نیاز به منابع کمتر.
- کلاسی: مناسب برای پروژههای قدیمیتر یا نیاز به متدهای خاص lifecycle.
استفاده از Hooks در کامپوننت های ری اکت
کامپوننتهای تابعی
- مدیریت وضعیت ساده: با معرفی Hooks در نسخه 16.8 ری اکت، کامپوننتهای تابعی توانستند به صورت کامل به امکانات پیشرفتهای مانند مدیریت وضعیت، اثرات جانبی و دسترسی به context دست پیدا کنند. این امر باعث شد که کامپوننتهای تابعی به انتخاب محبوبتری تبدیل شوند.
- کاهش پیچیدگی: استفاده از Hooks مانند useState و useEffect، امکان اضافه کردن منطق پیچیده به کامپوننتهای تابعی را بدون نیاز به استفاده از ساختارهای کلاسی فراهم میکند.
- مقیاسپذیری بالا: ترکیب Hooks با سایر ابزارهای ریاکت، مانند useReducer یا useContext، باعث شده که حتی پروژههای بزرگ و پیچیده نیز به راحتی از کامپوننتهای تابعی بهرهمند شوند.
مثال:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`Count is now: ${count}`);
}, [count]);
return <button onClick={() => setCount(count + 1)}>Increase</button>;
}
کامپوننتهای کلاسی
روش سنتی: پیش از معرفی Hooks، کامپوننتهای کلاسی تنها راه برای مدیریت state و استفاده از متدهای lifecycle بودند. متدهایی مانند componentDidMount و componentWillUnmount امکان مدیریت وضعیت و اثرات جانبی را فراهم میکردند.
نیاز به پیچیدگی بیشتر: استفاده از کلاسها به دلیل نیاز به مدیریت this و همچنین سینتکس پیچیدهتر میتواند چالشبرانگیزتر باشد.
استفاده از انواع کامپوننت ری اکت در پروژههای جدید
استفاده از کامپوننتهای تابعی
- اولویت در پروژههای مدرن: به دلیل سینتکس ساده، امکانات پیشرفتهای که توسط Hooks ارائه شده، و بهینهسازی عملکرد، کامپوننتهای تابعی به گزینه پیشفرض در پروژههای جدید ری اکت تبدیل شدهاند.
- انعطافپذیری بالا: به دلیل سبکتر بودن و سازگاری بهتر با تکنیکهای مدرن، کامپوننتهای تابعی به راحتی میتوانند در محیطهای مختلف از جمله SSR (با Next.js) یا Static Site Generation استفاده شوند.
استفاده از کامپوننتهای کلاسی
- استفاده در پروژههای قدیمیتر: همچنان در کدهای Legacy یا پروژههایی که پیش از معرفی Hooks ساخته شدهاند، کامپوننتهای کلاسی نقش مهمی ایفا میکنند.
- تبدیل به تابعی: بسیاری از تیمهای توسعه در حال تبدیل کامپوننتهای کلاسی قدیمی به تابعی هستند تا از مزایای کدنویسی مدرن بهرهمند شوند.
در حالی که کامپوننتهای تابعی به دلیل انعطاف، عملکرد بهتر، و سازگاری با امکانات مدرن مانند Hooks انتخاب محبوبی هستند، کامپوننتهای کلاسی همچنان در پروژههای موجود و برای موارد خاص کاربرد دارند.
جدول مقایسه کلی انواع کامپوننت ری اکت (کلس کامپوننت و فانکشنال کامپوننت)
ویژگی | کامپوننتهای تابعی
(Functional Components) |
کامپوننتهای کلاسی
(Class Components) |
---|---|---|
تعریف و ساختار | تابعی با سینتکس ساده و مستقیم JSX | از کلاسها ارثبری میکند و نیاز به ساختار پیچیدهتر دارد |
مدیریت state و lifecycle | نیاز به استفاده از Hooks مانند useState و useEffect |
به طور پیشفرض از state و lifecycle methods مانند componentDidMount و componentWillUnmount پشتیبانی میکند |
سینتکس و خوانایی کد | سادهتر و خواناتر، کد مختصرتر و تمیزتر | پیچیدهتر به دلیل استفاده از کلاسها و ساختارهای اضافی |
عملکرد | معمولاً سریعتر به دلیل ساختار سادهتر | ممکن است کمی کندتر باشد به دلیل ویژگیهای پیچیدهتر |
استفاده از Hook | از ویژگیهای Hooks پشتیبانی میکند | به Hooks نیاز ندارد، زیرا پیش از معرفی آنها از متدهای کلاس استفاده میشد |
استفاده در پروژههای جدید | بسیار محبوب در پروژههای جدید و مدرن | در پروژههای قدیمی و برخی موارد خاص استفاده میشود |
سازگاری با ریاکت | به طور کامل با ریاکت و توسعههای جدید آن سازگار است | سازگاری دارد، ولی به تدریج کمتر استفاده میشود |
جمعبندی:
در این مقاله به انواع کامپوننت ری اکت پرداختیم و کامپوننت های تابعی و کلاسی یا فانکشال کامپوننت و کلس کامپوننت ها را با هم مقایسه کردیم. به طور خلاصه:
- کامپوننتهای تابعی: سادگی، خوانایی بالا و استفاده از Hooks باعث شدهاند که این نوع کامپوننتها در پروژههای جدید محبوبیت زیادی پیدا کنند. آنها برای پروژههای مدرن و سادهتر گزینه بهتری هستند.
- کامپوننتهای کلاسی: این نوع کامپوننتها پیش از معرفی Hooks در ری اکت، برای مدیریت state و lifecycle ضروری بودند، اما حالا کمتر استفاده میشوند و بیشتر در کدهای قدیمیتر یافت میشوند.
در نهایت، با توجه به پیشرفتهای اخیر در ری اکت، کامپوننتهای تابعی با Hooks به گزینهای استاندارد و محبوب برای توسعهدهندگان ری اکت در بین انواع کامپوننت ری اکت تبدیل شدهاند.
مطالعه بیشتر در رفرنس های خارجی:
React Components (react.dev)
What are Components and Types of Components in React JS (medium.com)
React Component Types (w3schools)
لیست کامل مقالات ” ری اکت ” ویکس سِوِن در لینک زیر :