قبل از اینکه سراغ قابلیت استفاده مجدد React Code برویم، یک مرور کلی از React و محبوبیت این فریمورک را داشته باشیم.
مروری بر React
React یکی از محبوب ترین فریم ورک های JavaScript front-end برای ساخت رابط های کاربری می باشد. React که توسط متا(فیس بوک) توسعه یافته است، به دلیل سادگی، انعطاف پذیری و مقیاس پذیری، طرفداران زیادی در جامعه توسعه وب به دست آورده است. محبوبیت React را می توان به معماری مبتنی بر مؤلفه آن نسبت داد، که به توسعه دهندگان اجازه می دهد رابط های کاربری پیچیده را به قطعات کوچک و قابل استفاده مجدد تقسیم کنند. سپس میتوان این اجزای کوچکتر برای ایجاد سریع رابط های کاربری
گستردهتر و پیچیدهتر ترکیب کرد.
با این حال، با افزایش اندازه و پیچیدگی برنامه های React، مدیریت موثر پایگاه کد به طور فزاینده ای چالش برانگیز می شود. اینجاست که قابلیت استفاده مجدد کد وارد عمل می شود. قابلیت استفاده مجدد کد در React به تمرین نوشتن کد قابل استفاده مجدد اشاره دارد که می تواند در قسمت های مختلف یک برنامه کاربردی و حتی در بین برنامه های مختلف به اشتراک گذاشته شود. این به توسعه دهندگان کمک می کند تا در زمان صرفه جویی کنند، خطاها را کاهش دهند و مقیاس پذیری و نگهداری برنامه های خود را بهبود بخشند.
کامپوننت های React و اهمیت آنها در قابلیت استفاده مجدد
کامپوننت های React بخش اساسی برای دستیابی به قابلیت استفاده مجدد کد در برنامه React هستند. این به نوبت خود منجر به توسعه کارآمدتر و مقیاس پذیرتر می شود.
هنگامی که کامپوننت های قابل استفاده مجدد هستند، می توان آنها را به راحتی وارد بخش های مختلف برنامه یا در برنامه های مختلف کرد. این منجر به توسعه ساده تر و تکرار سریعتر برنامه ما می شود.
مقایسه تابعی و کلاسی کامپوننت ها از نظر قابلیت استفاده مجدد
کامپوننتهای تابعی و کلاسی دو نوع مؤلفه در React هستند و هر دو در مورد قابلیت استفاده مجدد، مزایا و معایب خاص خود را دارند.
کامپوننت های تابعی
کامپوننت های تابعی ساده تر از کامپوننت های کلاس هستند. آنها props را به عنوان ورودی می گیرند و عناصر UI را برمی گردانند. از آنجایی که روشهای حالت یا چرخه حیات ندارند، آزمایش و نگهداری آن ها آسانتر است.
یکی از مزیت های قابل توجه کامپوننت های تابعی این است که مختصرتر و خواناتر هستند که می تواند برای درک کد و ایجاد تغییرات در آن مفید باشد. آنها همچنین می توانند در مولفه های مرتبه بالاتر (HOCها) استفاده شوند، که عملکردهای قابل استفاده مجدد هستند که یک کامپوننت را بسته بندی می کنند و عملکرد اضافی را ارائه می دهند.
در اینجا یک مثال از یک کامپوننت تابعی ساده است که پیام خوش آمدگویی را نمایش می دهد:
function Welcome(props) {
return <h1>Hi, {props.name}!</h1>;
}
کامپوننت بالا را می توان در سراسر برنامه با ارسال مقادیر مختلف برای name prop استفاده مجدد کرد.
کامپوننت های کلاس
از طرف دیگر کامپوننت های کلاس عملکرد بیشتری دارند و نسبت به اجزای عملکردی قدرتمندتر هستند. آنها state دارند که به آنها امکان می دهد داده های خود را مدیریت کنند و UI خود را بر اساس تغییرات در آن داده ها به روز کنند. آنها همچنین دارای روشهای چرخه حیات هستند که به آنها اجازه میدهد تا اقدامات خاصی را در نقاط خاصی از چرخه عمر خود انجام دهند، مانند زمانی که کامپوننت پیاده سازی یا جدا شده است.
نقطه ضعف کامپوننت های کلاس این است که پرمخاطب تر و خواندن آنها نسبت به کامپوننت های تابعی سخت تر است. همچنین به دلیل وضعیت و روش های چرخه عمر، نگهداری و آزمایش آنها چالش برانگیزتر است.
با این حال، کامپوننت های کلاس می توانند بسیار قابل استفاده مجدد باشند، اگر به درستی طراحی شوند. با تفکیک state و عملکرد آنها به روشهای مختلف، کامپوننت های
کلاس میتوانند ماژولارتر شوند و استفاده مجدد آنها آسانتر شود. آنها همچنین می توانند در HOC ها و رندر prop ها مانند کامپوننت های تابعی استفاده شوند.
در اینجا یک مثال از یک کامپوننت کلاس است که یک تایمر شمارش معکوس نمایش می دهد:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: props.seconds };
}
tick() {
this.setState((state) => ({
seconds: state.seconds - 1,
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return <div>Seconds remaining: {this.state.seconds}</div>;
}
}
در کامپوننت بالا، state در سازنده و متد ()tick مدیریت میشود، در حالی که متدهای چرخه حیات ()componentDidMount و ()componentWillUnmount شروع و توقف تایمر را کنترل میکنند. این کامپوننت را می توان با ارسال مقادیر مختلف برای ثانیه ها مورد استفاده مجدد قرار داد.
کامپوننت Button
کامپوننت دکمه ای یک مثال ساده از یک کامپوننت قابل استفاده مجدد است که می تواند در یک برنامه کاربردی استفاده شود. دکمهها یک عنصر رابط کاربری رایج در اکثر برنامهها هستند و ایجاد یک کاربرد مجزا برای آنها میتواند کد را سادهتر و قابل استفادهتر کند.
در اینجا نمونه ای از کامپوننت دکمه در React آمده است:
function Button(props) {
return <button onClick={props.onClick}>{props.label}</button>;
}
در کامپوننت بالا، وقتی از کامپوننت برای سفارشی کردن رفتار و ظاهر دکمه استفاده میشود، میتوان برپایههای onClick و label انجام داد.
کامپوننت های ماژولی (Modal Component )
کامپوننت ماژول نمونه دیگری از کامپوننت های قابل استفاده مجدد است که می تواند در بخش های مختلف یک برنامه کاربردی استفاده شود. ماژول ها معمولاً برای نمایش اطلاعات اضافی یا ترغیب کاربر برای انجام یک اقدام استفاده می شوند.
در اینجا نمونه ای از ایجاد کامپوننت ماژول در React آورده شده است:
function Modal(props) {
return (
<div className="modal">
<div className="modal-content">{props.children}</div>
</div>
);
}
در کامپوننت بالا، برای رندر محتوای کامپوننت فرزند ماژول از پایه children استفاده میشود. این اجازه می دهد تا ماژول به راحتی سفارشی شود و در بخش های مختلف برنامه مورد استفاده قرار گیرد.
کامپوننت Input form
کامپوننت input فرم نوعی کامپوننت قابل استفاده مجدد هستند که می توانند برای ایجاد انواع مختلف input و فیلدهای کاربر مانند input متن، input رمز عبور، چک باکس و غیره استفاده شوند.
در اینجا مثالی از کامپوننت input فرم در React آورده شده است:
function FormInput(props) {
return (
<div>
<label>{props.label}</label>
<input type={props.type} value={props.value} onChange={props.onChange} />
</div>
);
}
در کامپوننت بالا، از نوع، مقدار و prop های onChange برای سفارشی سازی فیلد input استفاده می شود. از این کامپوننت می توان برای ایجاد انواع مختلف فیلدهای input با ارسال مقادیر مختلف برای این props استفاده کرد.
بهترین روش ها برای قابلیت استفاده مجدد کد در React
استفاده از Props و State برای انعطاف پذیرتر کردن کامپوننت
Props و State دو مفهوم اساسی در React هستند که به توسعه دهندگان اجازه می دهند کامپوننت های انعطاف پذیر و قابل استفاده مجدد ایجاد کنند. با استفاده از props و state، کامپوننت را می توان سفارشی کرد و با موارد استفاده مختلف تطبیق داد و آنها را همه کاره تر و کارآمدتر کرد. در اینجا برخی از بهترین روش ها برای استفاده از props و state در اجزای React آورده شده است:
استفاده از Props برای سفارشی کردن کامپوننت ها
Props برای انتقال داده ها از یک کامپوننت والد به یک کامپوننت فرزند استفاده می شود. با استفاده از لوازم، کامپوننت را می توان سفارشی کرد و انعطاف پذیرتر کرد. به عنوان مثال، یک کامپوننت دکمه میتواند دارای برچسبی باشد که به آن اجازه میدهد متن متفاوتی را روی دکمه نمایش دهد.
در اینجا یک مثال از یک کامپوننت دکمه است که از props برای سفارشی کردن برچسب استفاده می کند:
function Button(props) {
return <button>{props.label}</button>;
}
در کامپوننت بالا، از برچسب برای سفارشی کردن متن دکمه استفاده می شود. این باعث می شود که کامپوننت دکمه همه کاره تر و قابل استفاده مجدد باشد.
استفاده از State برای مدیریت داده های کامپوننت
State برای مدیریت داده ها در یک کامپوننت استفاده می شود. با استفاده از state می توان کامپوننت ها را پویاتر و پاسخگوتر کرد. به عنوان مثال، یک کامپوننت تایمر شمارش معکوس می تواند از وضعیت برای به روز رسانی رابط کاربری با زمان شمارش معکوس فعلی استفاده کند.
در اینجا یک مثال از یک کامپوننت تایمر شمارش معکوس است که از state برای مدیریت داده ها استفاده می کند:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: props.seconds };
}
tick() {
this.setState((state) => ({
seconds: state.seconds - 1,
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return <div>Seconds remaining: {this.state.seconds}</div>;
}
}
در کامپوننت بالا، از state برای مدیریت داده های ثانیه استفاده می شود، که سپس برای به روز رسانی رابط کاربری با زمان شمارش معکوس فعلی استفاده می شود. این امر باعث انعطاف پذیری و استفاده مجدد کامپوننت می شود، زیرا می توان آن را با زمان های مختلف شمارش معکوس سفارشی کرد.
استفاده باهم از Props و State
Props و State را می توان با هم استفاده کرد تا کامپوننت را انعطاف پذیرتر و همه کاره تر کند. با استفاده از props برای انتقال داده ها به یک کامپوننت و state برای مدیریت آن داده ها، می توان کامپوننت ها را با موارد استفاده مختلف سازگار کرد و پویاتر شد.
در اینجا نمونه ای از یک کامپوننت input فرم است که از props و state با هم استفاده می کند:
class FormInput extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.value };
}
handleChange(event) {
this.setState({ value: event.target.value });
}
render() {
return (
<div>
<label>{this.props.label}</label>
<input
type={this.props.type}
value={this.state.value}
onChange={this.handleChange.bind(this)}
/>
</div>
);
}
}
در کامپوننت بالا، از state مقدار برای مدیریت مقدار فیلد ورودی استفاده می شود، در حالی که از برچسب و نوع props برای سفارشی کردن فیلد ورودی استفاده می شود. این امر کامپوننت input فرم را انعطاف پذیرتر و همه کاره تر می کند، زیرا می توان آن را با برچسب ها و انواع ورودی های مختلف سفارشی کرد.
تفکیک Cross-Cutting متقابل به HOC
Cross-cutting مقطعی عملکردی هستند که در چندین کامپوننت در یک برنامه کاربردی استفاده می شود. نمونههایی ازCross-cutting متقابل شامل احراز هویت، ورود به سیستم و مدیریت خطا است. با تفکیکCross-cutting های مقطعی در HOC ها، عملکرد را می توان در یک مکان محصور کرد و قابلیت استفاده مجدد را بیشتر کرد.
در اینجا نمونه ای از HOC است که عملکرد احراز هویت را ارائه می دهد:
function withAuth(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = { isAuthenticated: false };
}
componentDidMount() {
// Perform authentication check here
const isAuthenticated = true; // replace with actual authentication check
this.setState({ isAuthenticated });
}
render() {
return this.state.isAuthenticated ? <WrappedComponent {...this.props} /> : null;
}
};
}
در مثال بالا، withAuth HOC یک بررسی احراز هویت را انجام می دهد و تنها در صورتی که کاربر احراز هویت شده باشد، کامپوننت پیچیده شده را ارائه می دهد. از این HOC می توان برای ارائه قابلیت احراز هویت به چندین کامپوننت در برنامه استفاده کرد.
تکنیک های دیگری نیز وجود دارد که در مقاله های بعدی به آن ها اشاره خواهد شد.