تعیین قیمت و اضافه کردن دکمه ی Order
Setting The Price And Adding The Order Button
محاسبه ی قیمت همبرگر
در این قسمت نوبت به بروزرسانی قیمت همبرگر و نمایش آن است. بهتر است که قیمت همبرگر را بالاتر از کنترل های کاربر قرار دهیم بنابراین به فایل BuildControls.js بروید و بالاتر از تابع map می گوییم:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
اگر یادتان باشد قیمت همبرگر را در state تعریف کرده بودیم بنابراین می توانیم آن را با this.state
دریافت کنیم. حالا اگر به مرورگر برویم و تعداد محتویات را کم و زیاد کنیم متوجه خواهیم شد که قیمت همبرگر ما اعشاری در می آید:

این مشکل به خاطر طبیعت جاوا اسکریپت است که باید آن را حل کنیم. ابتدا بهتر است قیمت را درون تگ های <strong> قرار دهیم تا بزرگتر و مشخص باشد:
1 |
<p>Current Price: <strong>{props.price}</strong></p> |
حالا می توانیم از تابع toFixed استفاده کنیم و قیمت همبرگر را فقط تا 2 رقم اعشار تعیین کنیم:
1 |
<p>Current Price: <strong>{props.price.toFixed(2)}</strong></p> |
بدین صورت قیمت در حد 2 رقم اعشار باقی می ماند و دیگر مشکل قبل را نخواهیم داشت.
ساخت دکمه ی ثبت سفارش
حالا باید یک Modal بسازیم تا خلاصه ای از سفارش را در اختیار ما قرار دهد. البته قبل از آن باید یک دکمه ی Checkout یا ثبت سفارش را ایجاد کنیم تا اگر کاربر روی آن دکمه کلیک کرد Modal برایش به نمایش در بیاید. برای شروع به فایل BuildControls.js بروید و دکمه ی Checkout را ایجاد کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const buildControls = (props) => ( <div className={classes.BuildControls}> <p>Current Price: <strong>{props.price.toFixed(2)}</strong></p> {controls.map(ctrl => ( <BuildControl key={ctrl.label} label={ctrl.label} added={() => props.ingredientAdded(ctrl.type)} removed={() => props.ingredientRemoved(ctrl.type)} disabled={props.disabled[ctrl.type]} /> ))} <button>ORDER NOW</button> </div> ); |
همانطور که می بینید تنها یک button ساده به کد اضافه کرده ام و درون آن مقدار ORDER NOW را قرار داده ایم. حالا به فایل BuildControls.module.css بروید تا استایل هایی به این دکمه اضافه کنیم:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
این استایل ها بر اساس سلیقه ی من آماده شده اند اما شما می توانید هر طور که خواستید آن ها را تغییر دهید. حالا به BuildControls.js برمی گردیم تا این کلاس ها را به دکمه ی خود اضافه کنیم:
1 |
<button className={classes.OrderButton}>ORDER NOW</button> |
حالا باید چک کنیم تا کاربر همبرگر خالی را سفارش ندهد! بنابراین باید مقدار حداقلی تعیین کنیم و فقط در آن حالت دکمه ی ORDER NOW را از حالت disabled خارج نماییم. برای شروع یک خصوصیت جدید به state اضافه می کنم:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
در این متد ابتدا یک کپی از ingredients درون state ایجاد می کنیم. سپس می خواهیم مقادیر (تعداد محتویات) را با هم جمع کنیم و فقط در صورتی اجازه ی ثبت سفارش را بدهیم که تعداد کل محتویات همبرگر حداقل 1 باشد (یعنی همربرگر خالی نباشد). برای این کار ثابتی به نام sum (مجموع) ساخته ایم تا مقادیر را در خود بگیرد. سپس با استفاده از Object.keys که پیش فرض خود جاوا اسکریپت است مقدار key های ingredients را به صورت یک آرایه گرفته ایم (مثل salad و bacon و…) اما ما مقدار آن ها را می خواهیم نه key ها را… بنابراین از متد map استفاده می کنیم تا مقادیر را بگیریم. استفاده از تابع map را بار ها برایتان توضیح داده ایم.
حالا باید از تابع ()reduce
استفاده کنیم تا تمام مقادیر را به یک مقدار تبدیل کنیم:
1 2 3 4 5 6 7 8 9 10 |
updatePurchaseState() { const ingredients = { ...this.state.ingredients }; const sum = Object.keys(ingredients).map(igKey => { return ingredients[igKey]; }).reduce((sum, el) => { return sum + el; }, 0); } |
قبلا با تابع ()reduce
کار کرده ایم و می دانیم چطور کار می کند. ما تمام مقادیر را گرفته ایم و با هم جمع زده ایم و initial value را هم صفر گذاشته ایم. بنابراین بدین شکل می توانیم مجموع تمام مقادیر را به دست بیاوریم. حالا باید setState را صدا بزنیم:
1 2 3 4 5 6 7 8 9 10 11 12 |
updatePurchaseState() { const ingredients = { ...this.state.ingredients }; const sum = Object.keys(ingredients).map(igKey => { return ingredients[igKey]; }).reduce((sum, el) => { return sum + el; }, 0); this.setState({ purchasable: sum > 0 }); } |
اگر sum از صفر بیشتر باشد خروجی برابر با true خواهد بود و مقدار purchasable را نیز برابر با true قرار می دهد، در غیر این صورت مقدار آن false خواهد شد. حالا باید این مقدار را به قسمت JSX پاس بدهیم:
1 2 3 4 5 6 7 8 9 10 11 12 |
return ( <Aux> <Burger ingredients={this.state.ingredients} /> <BuildControls ingredientAdded={this.addIngredientHandler} ingredientRemoved={this.removeIngredientHandler} disabled={disabledInfo} purchasable={this.state.purchasable} price={this.state.totalPrice} /> </Aux> ); |
حالا به BuildControls.js رفته و با استفاده از اطلاعات پاس داده شده دکمه را disable می کنیم:
1 |
<button className={classes.OrderButton} disabled={!props.purchasable}>ORDER NOW</button> |
علامت ! برای برعکس کردن مقدار است. اگر همبرگر purchasable (قابل خرید) باشد یعنی مقدار true دارد اما دکمه ی ما باید زمانی disabled شود که قابل خرید نباشد بنابراین مقدار را برعکس کرده ایم.
این کد هنوز تکمیل نشده است و این دکمه هیچ گاه فعال نخواهد شد چرا که اصلا تابع خودمان را صدا نزده ایم بنابراین به فایل BurgerBuilder.js برگردید و آن را درون متدهای addIngredientHandler و removeIngredientHandler اضافه کنید تا با هر بار تغییر محتویات همبرگر، قابل خرید بودن آن دوباره چک شود:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
اگر الان به مرورگر بروید با مشکل عجیبی روبرو می شویم! قرار بود محدودیت محتویات همبرگر 1 باشد یعنی حداقل یک پنیر خالی، یا یک گوشت خالی و … اما درون مرورگر تا 2 محتوا انتخاب نشود، دکمه ی ORDER NOW فعال نمی شود. به نظر شما دلیل آن چیست؟
همانطور که می دانید ثابت ingredients درون متد updatePurchaseState همان state قدیمی ما است:
1 2 3 |
const ingredients = { ...this.state.ingredients }; |
و به دلیل طبیعت setState (که در جلسات فصل های قبل توضیح دادیم) هنگامی که updatePurchaseState را فراخوانی می کنیم، از state قدیمی استفاده می کنیم! برای حل این مشکل می توانیم مقدار updatedIngredients را به این تابع پاس بدهیم:
مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکانپذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.
بدین صورت از ingredinets پاس داده شده با تابع استفاده می کنیم و دیگر نیازی به ساختن کپی از state نداریم. حالا اگر به مرورگر بروید دیگر مشکلی نخواهیم داشت.
- به جامع ترین دورهی React.js در وب فارسی خوش آمدید!
- مروری بر ویژگیهای ES6: کلیدواژههای let و const و توابع Arrow Functions
- مروری بر ویژگی های ES6: مفاهیم import و export و کلاس ها
- مروری بر ویژگی های ES6: اپراتورهای spread و rest + مبحث Destructuring
- نکات تکمیلی مربوط به جاوا اسکریپت
- راه اندازی محیط توسعه و پکیج create-react-app
- آشنایی با ساختار پوشه ها و فایل های پروژه
- آشنایی با JSX و محدودیت های آن
- ساخت یک کامپوننت ساده و واقعی
- نمایش خروجی پویا و درک props
- درک مفهوم state و کار با آن + مدیریت رویدادها
- آشنایی با hook در react.js (نسخه ی ۱۶٫۸ به بالا)
- انتقال متد بین کامپوننت ها به عنوان property
- استایل دهی عناصر در react (پایان فصل اول)
- پاسخ و حل تمرینات فصل اول
- نمایش محتوا بر اساس شرطی خاص
- روش صحیح نمایش شرطی عناصر + لیست ها در react
- تغییر state به شکل immutable
- کار با key و لیست های منعطف (پایان فصل ۲) + تمرینات
- پاسخ و حل تمرینات فصل دوم دوره ی React.js
- استایل دهی عناصر و کلاس های پویا
- رفع مشکل استایل های inline با کتابخانه ی Radium
- آشنایی با CSS Module در react
- پیاده سازی استایل های قبلی در CSS Module (پایان فصل سوم)
- اشکالزدایی (debug) برنامه های react: کار با developer tools مرورگر
- اشکالزدایی (debug): افزونه ی react developer tools و قابلیت Error Boundary
- فصل جدید و تغییر ساختار پروژه!
- تکمیل کدهای کامپوننت Cockpit.js
- نگاهی عمیق تر به کامپوننت های stateless و stateful
- دوره ی عمر کامپوننت ها (Lifecycle): ساخته شدن کامپوننت
- بررسی عملی چرخه ی زندگی کامپوننت ها: ایجاد کامپوننت (Creation)
- چرخهی زندگی کامپوننت ها (Lifecycle): بروزرسانی (Update)
- چرخهی ویرایش برای state و useEffect
- نگاهی عمیق تر به useEffect
- بهینه سازی کامپوننت های کاربردی و کلاس-محور
- نکات تکمیلی بهینه سازی + نحوه ی کار Virtual DOM
- حل مشکل تکی بودن عنصر ریشه ای در return
- Higher Order Component یا HOC چیست؟
- پاس دادن prop های ناشناخته و استفاده صحیح از State
- استفاده از propType
- استفاده از Ref ها (ارجاع) در react
- Ref ها در کامپوننت های کاربردی + معرفی مشکل Prop Chain
- حل مشکل زنجیره های prop با استفاده از context API
- دو روش دیگر استفاده از context API (پایان فصل چهارم)
- پروژه ی همبرگرساز (به فصل پنجم خوش آمدید!)
- تعیین state و ساختار اولیه ی پروژه
- ساخت کامپوننت Layout و طرح اولیه
- اضافه کردن کامپوننت محتویات همبرگر
- اعتبارسنجی با propType و نمایش همبرگر
- نمایش پویای همبرگر (پیاده سازی state)
- نمایش پویای همبرگر (پیام اولیه)
- نمایش پویای همبرگر (ایجاد ظاهر کنترل های کاربر)
- اتصال کنترل ها به state: دکمه ی More
- اتصال کنترل ها به state: دکمه ی less
- تعیین قیمت و اضافه کردن دکمه ی Order
- ساخت Modal خلاصه ی سفارش
- نمایش مشروط Modal خلاصه سفارش
- ساخت کامپوننت دکمه های تایید و کنسل کردن سفارش
- تکمیل کدها و ساخت کامپوننت Toolbar
- اضافه کردن لوگو و منوی Navigation به برنامه
- ایجاد منوی کشویی (side drawer)