ما توانستیم backdrop را به برنامه ی خود اضافه کنیم و همچنین کاری کنیم که با کلیک روی آن منوی کشویی به طور کامل بسته شود. در حال حاضر منوی کشویی ما همیشه باز است. در این قسمت می خواهیم دکمه ی Menu را نیز تکمیل کنیم تا بتوانیم با کلیک روی آن منوی کشویی در ری اکت را باز کنیم نه اینکه این منو همیشه باز باشد!
ما قصد داریم که دکمه ی Menu را به عنوان یک کامپوننت جداگانه در نظر بگیریم و شکل آن را نیز به شکل یک آیکون همبرگر بسازیم. برای انجام این کار به پوشه ی SideDrawer بروید و در آن یک پوشه ی دیگر به نام DrawerToggle بسازید که درون خود فایلی به نام DrawerToggle.js داشته باشد. همانطور که می دانید این کامپوننت نیز مانند دیگر کامپوننت های کاربردی ما شکل اولیه ی زیر را دارد:
import React from 'react'; const drawerToggle = (props) => ( ); export default drawerToggle;
فعلا تنها کاری که می کنیم اضافه کردن یک div به این کامپوننت است:
const drawerToggle = (props) => ( <div>MENU</div> );
همانطور که گفتم بعدا این div را تبدیل به یک آیکون همبرگر خواهیم کرد اما فعلا برای راحتی کار از div استفاده می کنیم. فایل را ذخیره کرده و وارد فایل Toolbar.js شوید. در مرحله ی اول باید DrawerToggle را درون فایل Toolbar.js وارد کنیم بنابراین:
import DrawerToggle from '../SideDrawer/DrawerToggle/DrawerToggle';
حالا در قسمت JSX به جای استفاده از div ساده ی زیر:
<div>MENU</div>
از کامپوننت خودمان استفاده می کنیم:
const toolbar = (props) => ( <header className={classes.Toolbar}> <DrawerToggle /> <div className={classes.Logo}> <Logo /> </div> <nav className={classes.DesktopOnly}> <NavigationItems /> </nav> </header> );
در مرحله ی بعد باید یک click listener به div درون فایل DrawerToggle.js اضافه کنیم بنابراین:
const drawerToggle = (props) => ( <div onClick={props.clicked}>MENU</div> );
در واقع انتظار داریم که از طریق props متدی را دریافت کنیم که با کلیک روی این div اجرا شود. بنابراین همین prop را در فایل Toolbar.js به عنصر <DrawerToggle> اضافه می کنیم:
<DrawerToggle clicked={props.drawerToggleClicked} />
حالا نوبت تعریف این متد است؛ از طرفی این متد را در Toolbar نداریم اما می توانیم آن را در Layout تعریف کرده و سپس آن را به DrawerToggle اضافه می کنیم بنابراین فایل Layout.js را باز کرده و می گوییم:
sideDrawerToggleHandler = () => { this.setState({ showSideDrawer: !this.state.showSideDrawer }) }
ما با این متد، مقدار showSideDrawer را خلاف مقدار فعلی اش تنظیم کرده ایم. در نظر اول این روش کاملا بی نقص است اما اگر دقیق تر نگاه کنید متوجه عیب این روش خواهید شد. قبلا گفته بودیم که اگر می خواهید از state درون setState استفاده کنید، نباید این کار را به شکل بالا انجام دهید چرا که setState به صورت نامتقارن (asynchronous) اجرا می شود بنابراین ممکن است نتایج به درستی نمایش داده نشود. بهتر است به جای آن از حالت تابعی setState استفاده کنیم:
sideDrawerToggleHandler = () => { this.setState((prevState) => { return { showSideDrawer: !prevState.showSideDrawer }; }); }
زمانی که تغییر state به state قبلی نیاز دارد (مانند مثال بالا) باید از این روش استفاده کنید. حالا در همین فایل به قسمت JSX رفته و آن را به Toolbar پاس می دهیم:
render() { return ( <Aux> <Toolbar drawerToggleClicked={this.sideDrawerToggleHandler} /> <SideDrawer open={this.state.showSideDrawer} closed={this.sideDrawerClosedHandler} /> <main className={classes.Content}> {this.props.children} </main> </Aux> ); }
فایل ها را ذخیره کرده و به مرورگر بروید. می بینید که دکمه ی Menu باعث باز شدن منوی کشویی ما می شود و کدهایمان بی نقص است اما هنوز هم شکل جالبی ندارد. در کنار فایل DrawerToggle.js یک فایل به نام DrawerToggle.module.css بسازید و محتویات زیر را در آن کپی کنید:
.DrawerToggle { width: 40px; height: 100%; display: flex; flex-flow: column; justify-content: space-around; align-items: center; padding: 10px 0; box-sizing: border-box; cursor: pointer; } .DrawerToggle div { width: 90%; height: 3px; background-color: white; } @media (min-width: 500px) { .DrawerToggle { display: none; } }
این ها استایل های CSS ای هستند که برای تغییر شکل دکمه ی Menu لازم داریم. حالا به فایل DrawerToggle.js برگردید و آن را به شکل زیر تغییر دهید:
import classes from './DrawerToggle.module.css'; const drawerToggle = (props) => ( <div className={classes.DrawerToggle} onClick={props.clicked}> <div></div> <div></div> <div></div> </div> );
یعنی ابتدا فایل CSS را وارد این کامپوننت کرده و به div اصلی کلاس DrawerToggle را بدهید. سپس 3 عدد div دیگر درون آن قرار دهید. حالا اگر به مرورگر برویم دکمه ی منوی همبرگری را می بینید:
نکته: اگر منوی کشویی در ری اکت به صورت پیش فرض باز است می توانید به فایل Layout.js رفته و مقدار State را روی false قرار دهید:
state = { showSideDrawer: false }
خواهید دید که کدها بدون نقص کار می کنند اما آیا این مسئله پایان کار است و برنامه ی ما تکمیل شده است؟ جواب خیر است! در واقع اگر از منظر کارکرد به برنامه نگاه کنید هیچ مشکلی وجود ندارد اما از منظر استفاده ی واقعی از برنامه، نمی توانیم آن را یک برنامه ی کامل بدانیم. منظور من نبود قابلیت های مختلف در برنامه نیست، بلکه عدم انجام بهینه سازی های مختلف برنامه است. به طور مثال چرا از prop-type validation استفاده نمی کنیم؟ ما در BurgerBuilder از prop-type استفاده کرده ایم (گفتیم که string و required باشد) اما از آنجایی که برنامه ی ما کاربر واقعی ندارد (داده های ورودی) و ما به صورت تیمی نیز برنامه نویسی نمی کنیم (هماهنگی در کدنویسی)، دلیلی برای استفاده از prop-type وجود ندارد. شما می توانید به صورت تمرین از prop-type استفاده کنید ولی ما فعلا چنین کاری انجام نمی دهیم. این در حالی است که اگر بخواهیم برنامه ی مان را به صورت واقعی روی سرور قرار بدهیم باید prop-type و موارد دیگر را چک کنیم. البته یک نوع بهینه سازی هنوز هم در برنامه ی ما قابل اجرا است! در قسمت بعدی که قسمت آخر این فصل و تکمیل پروژه می باشد با استفاده lifecycle ها برنامه مان را بهینه سازی خواهیم کرد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.