تو این مقاله که آخرین قسمت از سری الگوهای ری اکت هست، میخوام در مورد بهترین روش های استفاده از امکانات و قدرت ری اکت صحبت کنم. استفاده از الگوهای ری اکت باعث میشه کدهایی بنویسیم که به لحاظ کارایی و خوانایی سطح بالاتری داشته باشند.
تو این مقاله قصد دارم الگوهای ری اکت رو با بیان ساده شرح بدم . این مقاله برداشت آزادی از سایت الگوهای ری اکت است.
برای مطالعه قسمت های قبلی:
سرفصل های این قسمت:
Container component , Higher-order component, State hoisting, Controlled input
قبل از هر چیز، نگاهی به تعریف کانتینر داشته باشیم:
کانتینر ، وظیفه گرفتن دیتا و رندر کردن کامپوننت های مربوطه رو داره.
کامپوننت CommentList زیر رو در نظر بگیرید که با مپ زدن روی لیستی از کامنت ها، اسم نویسنده و متن نوشته شده رو نمایش میده:
const CommentList = ({ comments }) => ( <ul> {comments.map(comment => ( <li> {comment.body}-{comment.author} </li> ))} </ul> );
میتونیم کانتینر جدیدی بنویسیم که وظیفه گرفتن اطلاعات و همچنین رندر کردن اونها رو داشته باشه. تو تکه کد زیر از ajax برای درخواست زدن به سرور استفاده شده. (البته میتونید از fetch و axios استفاده کنید)
class CommentListContainer extends React.Component { state = { comments: [] } componentDidMount() { $.ajax({ // اینکه اینجا چه اتفاقی داره میافته مهم نیست url: "/my-comments.json", dataType: 'json', success: comments => this.setState({comments: comments}); }) } render() { return <CommentList comments={this.state.comments} /> } }
با لود شدن این کامپننت، درخواست Ajax زده میشه و داده ها به استیت کامپوننت CommentListContainer فرستاده میشه .داده های این state به کامپوننت CommentList داده میشه تا اونجا رندر بشه.
قبل از هر چیز، نگاهی به تعریف تابع مرتبه بالا داشته باشیم:
تابعی که تابع دیگری در ورودی میگیره و یا تابعی رو برمیگردونه
کامپوننت مرتبه بالا چیه؟
کامپوننت Greeting رو در نظر بگیرید:
const Greeting = ({ name }) => { if (!name) { return <div>Connecting...</div>; } return <div>Hi {name}!</div>; };
اگر این کامپونننت، پراپسی به اسم name بگیره، اون اسم رو همراه با کلمه "سلام" به نمایش میزاره در غیر این صورت عبارت Connecting... رندر میشه.
حالا چه جوری کامپوننت مرتبه بالا رو پیاده سازی کنیم؟
const Connect = ComposedComponent => class extends React.Component { constructor() { super(); this.state = { name: "" }; } componentDidMount() { // this would fetch or connect to a store this.setState({ name: "Michael" }); } render() { return <ComposedComponent {...this.props} name={this.state.name} />; } };
تابع Connect کامپوننت ComposedComponent رو برمیگردونه. این کامپوننت، Name که به عنوان آرگومان بهش پاس میدیم رو میگیره (که اینجا Michael هست) و رندر میکنه.
آخرین قدم، قرار دادن کامپوننت Greeting در تابع Connect که قبلا نوشتیم ( به این کار میگیم رپ کردن). در نتیجه قبل از لود شدن کامپوننت، رو صفحه عبارت Connecting... و بعد از لود شدن صفحه عبارت Hi Michael نمایش داده میشود.
const ConnectedMyComponent = Connect(Greeting);
این یکی از قدرتمندترین الگوها برای گرفتن اطلاعات و پاس دادنش به کامپوننت های تابعی هست.
کامپوننت های تابعی بر خلاف کلاس کامپوننت ها نمیتونن state داشته باشند ( تا قبل از اومدن ری اکت هوک این شکلی بود اما الان دیگه این جوری نیست).
به کامپوننت Name دقت کنید. تابع به صورت پراپس به این کامپوننت پاس داده میشه. توی کامپوننت پدر هم این مقدار رو به پاس میدیم. به این کار state hoisting گفته میشه.
class NameContainer extends React.Component { render() { return <Name ={newName => alert(newName)} />; } } // کامپوننت اسم که به صورت فانکشنال نوشته شده const Name = ({ }) => ( <input ={e => (e.target.value)} /> );
مثال پایین که در واقع همون مثال کامل شده بالا هست به ما نشون میده که به چه سادگی میتونیم تغییرات استیت رو با کامپوننت Name که داشتیم همراه کنیم:
class NameContainer extends React.Component { constructor() { super(); this.state = { name: "" }; } render() { return <Name ={newName => this.setState({ name: newName })} />; } }
در واقع state بجای اینکه توی کامپوننت Name باشه، به کانتینرش رسید. اینجوری به راحتی کامپوننت فانکشنالی نوشتیم که استیت نداره (ولی از طریق کانتینر بهش استیت دادیم) و بدون در نظر گرفتن مقدار همه جا کار میکنه !
در آخر توضیح این نکته ضروری هست که این الگو ، محدود به فانکشال کامپوننت نیست و به راحتی با کلاس کامپوننت ها قابلیت پیاده سازی داره.
کامپوننت ساده و uncontrolled زیر رو در نظر بگیرید:
<input type="text" />
میخواهیم این کامپوننت رو به کامپوننت Controlled تبدیل کنیم. با نوشتن state این کارو شروع میکنیم:
class ControlledNameInput extends React.Component { constructor() { super(); this.state = { name: "" }; // قرار دادن یک اسم خالی برای نمایش مقدار اولیه } render() { return <input type="text" value={this.state.name} />; } }
خوب تنها کاری که باید انجام بدیم، قرار دادن تابع هست که وظیفه تغییر state رو داره:
return ( <input value={this.state.name} ={e => this.setState({ name: e.target.value })} /> );
این ۴ نوشته با اسم الگوی ری اکت همین جا به پایان میرسه، سعی کردم با بیانی ساده بنویسم. با گفتن نظراتون به بهتر شدن نوشته هام کمک کنید. ممنون
سایر مقاله های من در ویرگول:
Follow me on social media
Telegram
Virgool