در قسمت قبل دکمه ی ORDER NOW را ایجاد کردیم و حالا نوبت آن است که modal خلاصه/گزارش آن را بنویسیم. ما این modal را به صورت یک کامپوننت جداگانه ایجاد خواهیم کرد؛ درون پوشه ی components یک پوشه ی دیگر به نام UI بسازید که مسئول نگهداری عناصر UI عمومی است. سپس درون آن یک پوشه به نام Modal ساخته و درون آن فایل Modal.js را ایجاد کنید. همچنین یک پوشه ی دیگر به نام Backdrop حاوی فایلی به نام Backdrop.js درون پوشه ی UI ایجاد کنید. دلیل اینکه Backdrop را جداگانه می سازیم این است که ممکن است بعدا در قسمت های دیگر برنامه (مانند منوی کشویی و...) نیز مورد استفاده قرار بگیرد.
ما با کدنویسی Modal.js شروع می کنیم:
import React from 'react'; const Modal = (props) => ( <div> {props.children} </div> ); export default Modal;
این modal یک کامپوننت بسیار ساده است که children را برمی گرداند یعنی استفاده از آن کاملا به ما بستگی دارد که چه چیزی به آن پاس بدهیم. بهتر است div ریشه ای را استایل دهی کنیم بنابراین درون پوشه ی Modal یک فایل به نام Modal.module.css بسازید و استایل های زیر را در آن قرار دهید:
.Modal { position: fixed; z-index: 500; background-color: white; width: 70%; border: 1px solid #ccc; box-shadow: 1px 1px 1px black; padding: 16px; left: 15%; top: 30%; box-sizing: border-box; transition: all 0.3s ease-out; } @media (min-width: 600px) { .Modal { width: 500px; left: calc(50% - 250px); } }
فایل را ذخیره کرده و آن را درون Modal.js وارد کنید:
import classes from './Modal.module.css';
حالا می توانیم کلاس را به div ریشه ای اضافه کنیم:
const Modal = (props) => ( <div className={classes.Modal}> {props.children} </div> );
می خواهیم این modal را درون BurgerBuilder.js نمایش دهیم بنابراین به این فایل بروید و آن را وارد کنید:
import Modal from '../../components/UI/Modal/Modal';
حالا به قسمت JSX این فایل می رویم تا Modal را اضافه کنیم. همانطور که می دانیم Modal فقط باید در شرایط خاصی نمایش داده شود که آن را تنظیم خواهیم کرد اما فعلا آن را به صورت عادی اضافه کنید:
return ( <Aux> <Modal /> <Burger ingredients={this.state.ingredients} /> <BuildControls ingredientAdded={this.addIngredientHandler} ingredientRemoved={this.removeIngredientHandler} disabled={disabledInfo} purchasable={this.state.purchasable} price={this.state.totalPrice} /> </Aux> );
حالا اگر مرورگر را با کنید متوجه می شوید که Modal ما به صفحه اضافه شده است:
دلیل خالی بودن آن هم این است که هنوز هیچ چیزی برایش ننوشته ایم. از آنجایی که فایل BuildBuger.js به اندازه ی کافی شلوغ شده است من میخواهم یک کامپوننت جدا برای تولید خلاصه ی سفارش ایجاد کنم. برای این کار وارد پوشه ی Burger شده و در آنجا یک پوشه ی دیگر به نام OrderSummary بسازید که حاوی فایلی به نام OrderSummary.js باشد. درون فایل OrderSummary یک تابع ساده می نویسیم:
import React from 'react'; const OrderSummary = (props) => { } export default OrderSummary;
از آنجایی که نمی خواهم div ریشه ای داشته باشم از همان عنصر Aux همیشگی استفاده می کنم:
import React from 'react'; import Aux from '../../../hoc/Auxx'; const OrderSummary = (props) => { return ( <Aux> </Aux> ); } export default OrderSummary;
حالا بقیه ی کدها را تکمیل می کنیم:
return ( <Aux> <h3>Your Order</h3> <p>A delecious burger with the following ingredients:</p> <ul> </ul> </Aux> );
قرار است لیست محتویات سفارش داده شده توسط کاربر را درون این <ul> نمایش بدهیم. می توانیم کدهای این قسمت را به صورت دستی بنویسیم اما من دوست دارم آن را به صورت پویا نمایش دهم بنابراین درون این کامپوننت اما خارج از قسمت return یک ثابت به شکل زیر تعریف می کنیم:
const ingredientSummary = Object.keys(props.ingredients).map(igKey => { return ( <li key={igKey}> <span style={{ textTransform: 'capitalize' }}>{igKey}</span>: {props.ingredients[igKey]} </li>); });
منطق این کد را بارها تمرین کرده ایم؛ قرار است با استفاده از props مقدار ingredients را دریافت کنیم سپس با روش همیشگی خودمان آن را تبدیل به یک آرایه کرده ایم. حالا متد map را روی این آرایه صدا می زنیم و به تعداد محتویات موجود تگ <li> اضافه می کنیم. تگ span بالا دارای استایل های inline است (textTransform: 'capitalize’ نام خصوصیات ingredients را با حروف بزرگ مینویسد و یک استایل عادی css است). دلیل وجود تگ span اضافه کردن همین استایل به آن است و گرنه به آن نیازی نیست؛ در واقع حالت خلاصه شده ی آن بدون استایل بدین شکل است:
{igKey}: {props.ingredients[igKey]}
قسمت igKey نام خصوصیت را به ما می دهد (مثلا salad یا bacon یا ...) و قسمت props.ingredients نیز مقدار آن را به ما می دهد. بنابراین خروجی شبیه salad: 1 می شود. یادتان باشد از آنجایی که محتوا را به صورت پویا اضافه می کنیم باید از key روی <li> غافل نشویم تا به خطا برنخوریم.
حالا می توانیم کدهایمان را در قسمت JSX تکمیل کنیم:
const OrderSummary = (props) => { const ingredientSummary = Object.keys(props.ingredients).map(igKey => { return ( <li key={igKey}> <span style={{ textTransform: 'capitalize' }}>{igKey}</span>: {props.ingredients[igKey]} </li>); }); return ( <Aux> <h3>Your Order</h3> <p>A delecious burger with the following ingredients:</p> <ul> {ingredientSummary} </ul> <p>Continue to Checkout?</p> </Aux> ); }
شما می توانید بر اساس سلیقه ی خودتان قسمت های مورد نظر را تغییر دهید. حالا باید به BurgerBuilder.js برویم تا از آن استفاده کنیم. ابتدا باید آن را import کنیم:
import OrderSummary from '../../components/Burger/OrderSummary/OrderSummary';
حالا به قسمت JSX می رویم و کدمان را بدین شکل تغییر می دهیم:
return ( <Aux> <Modal> <OrderSummary ingredients={this.state.ingredients}/> </Modal> <Burger ingredients={this.state.ingredients} /> <BuildControls ingredientAdded={this.addIngredientHandler} ingredientRemoved={this.removeIngredientHandler} disabled={disabledInfo} purchasable={this.state.purchasable} price={this.state.totalPrice} /> </Aux> );
یادتان نرود که برای OrderSummary مقدار ingredients را پاس بدهید چرا که به آن نیاز دارد. حالا اگر به مرورگر برویم می توانیم Modal خود را ببینیم:
در قسمت بعد باید کاری کنیم که Modal فقط در هنگام کلیک شدن روی دکمه ی ORDER NOW نمایش داده شود و همیشه در وسط صفحه قرار نگیرد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.