در ری اکت دو نوع کامپوننت میتوان نوشت ، یکی به شکل تابع و دیگری به شکل کلاس (class components , functional components).
داخل مثال hello world که پیشتر نوشتیم ، از کلاس کامپوننت ها استفاده کردیم
حالا میتونیم همین کد رو به شکل زیر به شکل functional component بنویسیم .
function App(props){
return (
<div className="App">
<header className="App-header">
<p>
Hello World , Hello Iran .
</p>
</header>
</div>
);
}
export default App;
این سوال شاید پیش بیاد که کدوم حالت بهتره؟
استفاده از توابع از نظر سینتکسی خیلی راحت تر از کلاس ها هستند .
قبل از ری اکت 16.8 تنها دلیلی که میتوانست کلاس را برتر از توابع کند ، امکان نوشتن setState داخل کلاس ها بود .
اما با ایجاد hooks در ری اکت 16.8 این قابلیت پیش آمد که تمام life cycle ری اکت را در functional Components داشته باشید .
به کد زیر دقت کنید :
import React, { useState } from 'react';
function App() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default App;
ری اکت برای تبدیل کردن کدها به یک نسخه قابل قبول در جاوا اسکریپت نیاز به یک کامپایلر دارد . این کامپایلر به نام babel شناخته شده .
اگر ما کدهای کلاس کامپوننت ها را با توابع در babel مقایسه کنیم ، متوجه میشیم که کلاس ها خروجی بسیار سنگینی نسبت به توابع دارند .
با مقایسه خروجی ها متوجه حجم زیاد خروجی های کلاس کامپوننت ها میشویم .
کامپوننت های ری اکت دارای چرخه های زیادی هستند .
معروفترین ها را در این سند میگیم . اما باقی چرخه ها به علت deprecate شدن و یا کمتر استفاده شدن ، در این سند نیستند و ارجاع داده میشند به لینک ری اکت .
در کلاس های constructor ها سازنده مقادیر پیشفرض کلاس هستند . کاری که constructor ها داخل شی گرایی در همه زبان ها کار مقدار سازی اولیه را بر عهده دارند .
داخل لایبرری ری اکت ، این تابع عمدتا به منظور تعریف state ها و bind کردن توابع داخل کلاس کاربرد دارد .
اما در مورد functional components این موارد به شکل ثابت ها تعریف میشوند .
مثال کلاس کامپوننت ها :
class A extends Component {
constructor(props){
super(props);
this.state={
grades:['a','b','c'],
name : '',
family : ''
};
}
...
}
مثال در توابع :
function A(props){
...
const [grades , setGrades]=useState(['a','b','c']);
const [name , setName]=useState('');
const [family , setFamily]=useState('');
...
}
این تابع فقط داخل کلاس کامپوننت ها کاربرد دارد در واقع این تابع همراه خود this.props و this.state را به داخل بدنه کامپوننت میارد .
این تابع زمانی که بارگذاری کامپوننت به صورت کامل به اتمام رسید ، کار خود را شروع میکند .
خیلی بهتر بخوایم بگیم ، زمانی که کامپوننت بارگزاری شود ، هر آنچه داخل این تابع باشد اتفاق میفتد . شبیه به کار onLoad در جاوا اسکریپت
این تابع به کامپوننت ما میگه که زمانی که یک state به روز بشه ، کامپوننت رو مجدد render کن .
این تابع دو مقدار میگیره به اسم nextProps, nextState . در واقع بررسی میکنیم که state یا props به سمت کامپوننت میاد ، آیا با مقادیر قبلی یا هر شرط دیگری که ما میدونیم ، قابل بررسی هست و نیاز به بروزرسانی کامپوننت دارد یا خیر.
اگر کامپوننت به روز شد و به روز رسانی موفقیت آمیز بود ، این تابع کار میکند و هر آنچه که در بدنه آن نوشته شده باشد اجرا میشود .
این تابع برای کلاس کامپوننت های نوشته شده است و برای توابع باید از useEffect که معادل این تابع است استفاده کنیم .
useEffect یک هوک برای سنجش تغییرات کامپوننت در کلاس های تابعی هست که کاری مشابه componentDidUpdate, componentWillUnmount , componentDidmount را انجام میدهد .
این تابع در کلاس کامپوننت ها کاربرد دارد و وظیفه این را بر عهده دارد که بعد از خروج از کامپوننت ، یک سری عملیات انجام دهد .
عمدتا توابعی که به صورت async هستند ، بعد از خروج از کامپوننت ها همچنان به کار خود ادامه میدهند .
مثلا شما یک setInterval نوشتید که هر 10 ثانیه یک عملیاتی را انجام دهد .
حالا از صفحه و کامپوننت خارج شدید . قاعدتا باید clearInterval اتفاق بیفتد . در غیر این صورت بدنه اینتروال همچنان ادامه خواهد داشت .
clearInetrval را در این تابع مینویسیم که به کامپوننت بگیم بعد از خروج ، حتما تابع async رو متوقف کن
این تابع که به تازگی معرفی شده دو مقدار دارد . error, info .
زمانی که یک خطایی در کامپوننت رخ دهد ، به کمک این تابع میتوانید جلو یک سری ارور ها و exception هایی که ری اکت به کاربر نمایش میدهد را بگیرید .
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logComponentStackToMyService(info.componentStack);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}