در جلسات قبل ساختار تمام پروژه را تغییر داده و آن را بهینه سازی کردیم. حالا کدهای بسیار تمیزتر و خواناتری داریم و مشخص است که هر کامپوننت مسئول چه کاری می باشد. در این جلسه می خواهیم نگاهی عمیق تر به مفهوم stateful و stateless داشته باشیم.
ما زمانی به کامپوننت ها stateful (به معنی «دارای state - «state یعنی وضعیت) می گوییم که state داشته باشند و آن را مدیریت کنند. دقیقا مانند کامپوننت App.js در پروژه خودمان:
class App extends Component { state = { persons: [ { id: 'asfa1', name: 'Max', age: 28 }, { id: 'vasdf1', name: 'Manu', age: 29 }, { id: 'asdf11', name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false }
همانطور که در کد بالا می بینید App دارای State است و آن را نیز مدیریت می کند.
نکته اینجاست که با معرفی react 16.8 دیگر نمی توان گفت کامپوننت های کلاس محور Stateful و کامپوننت های کاربردی stateless هستند. قبل از react 16.8 اینطور گفته می شد اما حالا با معرفی hook ها در react، کامپوننت های کاربردی نیز می توانند state داشته باشند (دستور useState). بنابراین در ذهن خود داشته باشید که کامپوننت های کاربردی نیز می توانند stateful باشند.
توصیه ما این است که تا حد امکان از کامپوننت های کاربردی stateless (بدون state) استفاده کنید و فقط چند کامپوننت محدود دارای State داشته باشید. با پیروی از این روش، مدیریت برنامه برایتان بسیار راحت تر می شود. از آنجا که جریان حرکت داده ها منطقی می شود، به راحتی می فهمید که State در چه قسمت هایی تغییر می کند و بقیه کامپوننت ها فقط برای نمایش UI هستند. نگهداری و مدیریت چنین برنامه هایی بسیار راحت تر است.
بنابراین می توانیم نکات مهم را بدین صورت دسته بندی کنیم:
ماهیت
کامپوننت های کلاس-محور (class-based)، کلاس هایی هستند که شیء Component از کتابخانه react را Extend می کنند. مثلا Class App extends Component
کامپوننت های کاربردی (functional) تنها توابع جاوا اسکریپتی هستند که کدهای JSX را برگردانده و UI می سازند.
دسترسی به State
کامپوننت های کلاس-محور (class-based)، به راحتی دارای state بوده و می توانند آن را تغییر بدهند. این نوع کامپوننت ها برای دسترسی به state و props از کلیدواژه this استفاده می کنند (در مورد prop بعدا صحبت میکنم).
کامپوننت های کاربردی (functional) تا قبل از react 16.8 دارای state نبوده اند اما با معرفی hook ها در react 16.8 و دستور useState می توانند دارای State باشند و آن را مدیریت کنند. این نوع کامپوننت ها برای دسترسی به props نیازی به کلیدواژه ندارند.
دسترسی Lifecycle Hooks
در آینده در مورد Lifecycle Hooks صحبت میکنیم اما فعلا بدانید که کامپوننت های کلاس محور می توانند از Lifecycle Hooks استفاده کنند اما کامپوننت های کاربردی (در حال حاضر) نمی توانند از آن ها استفاده کنند.
از کدام استفاده کنم؟
بر اساس توصیه ما مبنی بر استفاده از کامپوننت های کاربردی در حد ممکن می توان گفت:
زمانی که نیاز به مدیریت state دارید و نمی خواهید یا نمی توانید از useState Hook استفاده کنید و یا اگر می خواهید به Lifecycle Hooks دسترسی داشته باشید از کامپوننت های کلاس محور استفاده کنید. در تمام موقعیت های دیگر از کامپوننت های کاربردی استفاده کنید.
Hook ها ویژگی بسیار جدیدی در react هستند بنابراین هنوز بازار کار به آن عادت نکرده است و اکثر پروژه ها به شکل قدیمی انجام می شود بنابراین ما در طول این دوره، زمانی که نیاز به استفاده از state داشته باشیم از کامپوننت های کلاس-محور استفاده کرده و تنها در آخر دوره پروژه خود را تبدیل به یک پروژه با useState hooks میکنیم تا شما هر دو روش را یاد بگیرید.
حالا برویم سراغ this.props ... من تا این جلسه چیزی از this.props به شما نگفته بودم اما در این جلسه به صورت ساده با آن آشنا می شویم. مسئله اینجاست که تنها کامپوننت های کاربردی نیستند که props دریافت می کنند بلکه کامپوننت های کلاس-محور نیز توانایی دریافت props را دارند.
به طور مثال به فایل index.js در پروژه خودمان می رویم:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './containers/App'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<App />, document.getElementById('root')); registerServiceWorker();
همانطور که می بینید این فایل کدهای زیادی ندارد اما کامپوننت App در این قسمت مورد استفاده قرار میگیرد! بنابراین می توانیم از همینجا یک prop به آن بدهیم!
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './containers/App'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<App appTitle="Person Manager" />, document.getElementById('root')); registerServiceWorker();
انتخاب نام AppTitle برای این prop سلیقه ای است. شما می توانید هر نام دیگری را که دوست داشتید برای appTitle انتخاب کنید. مقدار appTitle را برابر با یک رشته ساده به نام person manager قرار داده ایم که به زبان فارسی یعنی «مدیریت کننده افراد». اگر دقت کرده باشید برنامه ای که ما نوشته ایم افراد مختلف را مدیریت می کند (مثلا نام آن ها را با استفاده از input مورد نظر تغییر می دهد، با کلیک آن ها را حذف می کند، با استفاده از دکمه Toggle Persons آن ها را مخفی یا آشکار می کند و الی آخر...). با این همه تمام این موارد سلیقه ای است و شما می توانید هر چیز دیگری را نیز انتخاب کنید.
حالا به فایل App.js برگردید و به قسمت استفاده از کامپوننت Cockpit بروید:
return ( <div className={classes.App}> <Cockpit showPersons={this.state.showPersons} persons={this.state.persons} clicked={this.togglePersonsHandler} /> {persons} </div> );
ما می توانیم در این قسمت از appTitle استفاده کنیم اما از آنجا که درون یک کامپوننت کلاس-محور هستیم باید کلیدواژه this را نیز همراه آن بیاوریم:
return ( <div className={classes.App}> <Cockpit title={this.props.appTitle} showPersons={this.state.showPersons} persons={this.state.persons} clicked={this.togglePersonsHandler} /> {persons} </div> );
اکنون می توانیم به فایل Cockpit.js برویم و این prop پاس داده شده را نمایش بدهیم:
return ( <div className={classes.Cockpit}> <h1>{props.title}</h1> <p className={assignedClasses.join(' ')}>This is really working!</p> <button className={btnClass} onClick={props.clicked}>Toggle Persons </button> </div> );
در واقع به جای استفاده از رشته Hi, I’m a react app از props.title استفاده کرده ایم. حالا اگر به مرورگر بروید می بینید که نام برنامه به Person Manager تغییر پیدا کرده است. در قسمت بعدی در رابطه با Lifecycle ها صحبت می کنیم.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.