همانطور که در قسمت اول گفته شد، React برای اینکه بتواند تگها را در زمان اجرا و به صورت پویا به روز کند، وضعیت فعلی تگها را دنبال میکند و در صورت وقوع تغییرات، تگها را به روز میکند. به این حالت Stateful گفته میشود. تگهای ساخته شده توسط React دو وضعیت را دارند. یکی وضعیت اولیه که به مرورگر ارسال شده، در حال نمایش است و ثابت، و دیگری در پشت زمینه در فایل جاوااسکریپت، در انتظار وقوع تغییری. React این دو وضعیت را با هم مقایسه میکند و اگر بین آنها تفاوتی وجود داشت، تغییرات را اعمال میکند.
در React.createClass به همراه متدهای داخلی React میتوانیم برای یک کامپوننت، وضعیتی اولیه را مشخص کنیم، تغییرات را دنبال کنیم و وضعیت فعلی را تغییر دهیم. برای روشن شدن نحوه کار، مثال قسمت قبل را که یک منو از نوشیدنیها بود، اینطور تغییر میدهیم که کاربر بتواند با inputها و یک دکمه، به لیست نوشیدنیها، مورد تازهای را اضافه کند:
var hotDrinks = [ { item: "Tea", price: "7000" }, { item: "Espresso", price: "10000" }, { item: "Hot Chocolate", price: "12000" } ]; var MenuItem = React.createClass({ render: function () { return ( <li className="list-group-item"> <span className="badge">{this.props.price}</span> <p>{this.props.item}</p> </li> ) } }); var Menu = React.createClass({ getInitialState: function () { return { menuList: this.props.data }; }, componentDidMount: function () { var component = this; $("#btnAddNewItem").click(function () { component.state.menuList.push( { item: $("#textInputItemName").val(), price: $("#textInputItemPrice").val() }); component.setState({ menuList: component.state.menuList }); }); }, render: function () { return ( <div className="row"> <div className="col-md-4"> <ul className="list-group"> {this.state.menuList.map(item => <MenuItem {...item} />)} </ul> </div> </div> ) } }); ReactDOM.render( <Menu data={hotDrinks} />, document.getElementById("reactTestContainer") );
توضیح کامپوننت Menu
getInitialState، componentDidMount، setState، state و render همگی از کتابخانه React هستند. اگر intelisense و code snippets مخصوص React را در VSCode نصب کرده باشید، دسترسی به سایر متدها و خاصیتهای کتابخانه سادهتر است.
شیء state، وضعیت کنونی کامپوننت است. وقتی دادهای را به state اختصاص میدهیم، آن را به عنوان وضعیت اولیه در نظر میگیرد. با تغییر داده، React وضعیت کامپوننت را تغییر یافته حساب میکند و به صورت خودکار تگها را دوباره با دادههای تازه میسازد. دادههای state همان دادههایی هستند که تگها با آنها ساخته میشوند؛ در بخش render.
getInitialState مثل یک سازنده عمل میکند؛ مقدار ورودی کامپوننت را به یک شیء اختصاص میدهد و آن را برمیگرداند. به کجا؟ به state. یعنی menuList عضوی از شیء state میشود. در مثال بالا و در این متد، لیست نوشیدنیها به menuList اعمال میشود.
componentDidMount باید حتما قبل render تعریف شود، به این دلیل که زمان اجرایش باید حتما بعد از اولین render باشد. این متد وظیفه دارد تغییرات مورد نظر ما را در سطح کد یا رابط کاربری دنبال کند. اگر تغییر دلخواهی به وجود آمد، وضعیت کامپوننت را به روز میکند که بعد از آن React به صورت خودکار تگها را دوباره میسازد. در مثال بالا متد به رویداد کلیک یک دکمه گوش میدهد. اگر کلیک زده شد، نام نوشیدنی جدید و قیمت آن را از inputها میخواند و به عنوان یک آیتم جدید به menuList در state اضافه میکند. اما هنوز یک قدم مانده و بدون آن React، شیء state را تغییر یافته به حساب نمیآورد. در بخش setState وضعیت جاری کامپوننت را با تغییرات اعمال شده، جایگزین میکنیم. در این نقطه React به صورت خودکار به سراغ render میرود و ادامه داستان!
همانطور که قبلا گفته شد، React.createClass و React.Component فقط در Syntax با هم تفاوت دارند. در نتیجه این مثال را میشود در حالت React.Component هم اجرا کرد.
در قسمت بعد موضوع دیگری را به نام Composability شرح میدهیم. مبحثی ساده با مثال که نشان میدهد چطور کامپوننتها را مستقل از هم بسازیم و در عین حال با هم استفاده کنیم.