نمایش پویای همبرگر (پیاده‌سازی state)

(Dynamic Hamburger Display (state Implementation

23 بهمن 1399
نمایش پویای همبرگر (پیاده سازی state)

در قسمت قبلی همبرگر را در مرورگر خودمان نمایش دادیم اما به جای آن که کدهای آن را از کاربر دریافت کنیم، خودمان به صورت دستی آن را کدنویسی کردیم. برای مدیریت داده های ورودی کاربر و دستور العمل های او باید درون فایل BurgerBuilder.js یک state تعریف کرده و آن را مدیریت کنیم. همانطور که در جلسات قبل توضیح دادیم دو روش برای پیاده سازی state در کامپوننت های کلاس-محور وجود داشت. راه اول استفاده از constructor بود:

    constructor (props) {
        super(props);
        this.state = {مقادیر دلخواه شما}
    }

و راه تعریف State به صورت یک property ساده:

    state = {
        
    }

من از روش دوم استفاده می کنم چرا که راحت تر و همچنین جدید تر است. حالا بیایید کدهای state را بنویسیم:

    state = {
        ingredients: {
            salad: 1,
            bacon: 1,
            cheese: 2,
            meat: 2
        }
    }

فعلا برای state یک شیء جاوا اسکریپتی در نظر گرفته ایم که مواد اولیه پیش فرض را دارد (شما می توانید مقادیر را بسته به سلیقه خودتان تغییر دهید). بعدا موارد بیشتری به state اضافه خواهیم کرد (مانند قیمت) اما فعلا فقط می خواهیم مشکل همبرگر را حل کنیم. پس از تکمیل کدهای state باید آن را به همبرگر خود پاس بدهیم، بنابراین:

    state = {
        ingredients: {
            salad: 1,
            bacon: 1,
            cheese: 2,
            meat: 2
        }
    }

    render() {
        return (
            <Aux>
                <Burger ingredients={this.state.ingredients}/>
                <div>Build Controls</div>
            </Aux>
        );
    }

حالا به فایل Burger.js میرویم تا این مقادیر را دریافت کرده و نمایش دهیم. باید توجه کرد که ingredient یک شیء است و آرایه نیست، بنابراین نمی توانیم با استفاده از متدهایی مثل map درون آن گردش کرده و اطلاعات را نمایش دهیم. باید ابتدا آن را تبدیل به یک آرایه کرده و سپس از آن استفاده کنیم. انجام این کار اصلا سخت نیست؛ شیء ای در جاوا اسکریپت وجود دارد که نام آن Object است (بله یک object به نام Object) و متدی به نام keys دارد که key های یک شیء خاص را به صورت یک آرایه از آن خارج می کند. بنابراین برای شیء ingredients ما رشته های salad و bacon و cheese و ... را خواهد داشت (اینها key بودند و value همان تعدادشان بود). در نتیجه می گوییم:

    const transformedIngredients = Object.keys(props.ingredients);

حالا می توانیم همین کد را به متد map متصل کنیم:

    const transformedIngredients = Object.keys(props.ingredients).map(igKey => {
        
    });

همانطور که می دانید متد map یک تابع را روی تک تک اعضای یک آرایه خاص اجرا می کرد. ما اینجا برای پارامتر map، پارامتری به نام igKey (مخفف ingredient key) را داده ایم؛ در واقع igKey تک تک مواد اولیه (مانند salad و cheese و meat و ...) است، اگر یادتان نمی آید به قسمت های «مروری بر ES6» و معرفی تابع map برگردید. حالا باید کدهای درون تابع را تکمیل کنیم. ما می خواهیم درون این تابع key ها را (که به شکل رشته هستند) تبدیل به آرایه ای کنیم که تعداد اعضای آن برابر با تعداد ingredient خاص آن باشد. مثلا اگر 2 عدد cheese (پنیر) داریم، می خواهم که رشته cheese (به عنوان key) تبدیل به آرایه ای با 2 عضو شود. مهم نیست که این عضوها چه باشند، فقط باید 2 عضو باشند. بنابراین:

    const transformedIngredients = Object.keys(props.ingredients).map(igKey => {
        return [...Array(props.ingredients[igKey])];
    });

تابع ()Array یک تابع جاوا اسکریپتی است که به عنوان پارامتر تعداد خاصی را می گیرد و سپس یک آرایه با همان تعداد اعضا می سازد. به طور مثال (3)Array یعنی یک آرایه با سه عضو خالی بساز. حالا در اینجا یک آرایه را return کرده ایم و درون آن از اپراتور spread استفاده کرده ایم، سپس یک آرایه جدید درون همین آرایه ساخته ایم که تعداد اعضایش برابر با تعداد هر کدام از مواد اولیه است. props.ingredient که به شیء ما دسترسی پیدا می کند و سپس igKey هم که key های ما را در خود دارد (اگر متوجه نمی شوید تابع map را مرور کنید) بنابراین با استفاده از key به مقدار دسترسی پیدا می کنیم و آن را به Array می دهیم. تا این جای کار یک آرایه خالی داریم که به تعداد مواد اولیه، عضو خالی دارد.

حالا دوباره متد map را روی همین آرایه صدا می زنیم. ما به خود عنصر آرایه کار نداریم بلکه با index آن کار خواهیم داشت بنابراین:

    const transformedIngredients = Object.keys(props.ingredients).map(igKey => {
        return [...Array(props.ingredients[igKey])].map((_,i) => {
            
        })
    });

از آنجایی که با خود عنصر کاری نداشتم، پارامتر آن را _ انتخاب کرده ایم (مهم نیست که ()Array با چه چیزی تابع ما را پُر می کند) و برای index هم حرف i را قرار داده ام. حالا درون این تابع می گوییم:

    const transformedIngredients = Object.keys(props.ingredients).map(igKey => {
        return [...Array(props.ingredients[igKey])].map((_,i) => {
            return <BurgerIngredient key={igKey + i} type={igKey} />;
        })
    });

از آنجایی که درون یک آرایه هستیم و از متد map استفاده کرده ایم، باید key را داشته باشیم (در جلسات قبل توضیح دادیم که key در چنین حالتی اجباری است). برای ساختن یک id خاص و یکتا نام ماده اولیه (مثلا cheese) را با i جمع کرده ایم مثلا cheese1 و cheese2 و ... یادتان باشد که i همان index بود بنابراین مقدارش در هر دور یکی افزایش پیدا می کند (0 و 1 و 2 و ...). سپس برای type نیز همان igKey را داده ایم.

اگر کد برایتان پیچیده است، می توانید console.log های مختلفی بین آن اضافه کنید تا روند کار را مرحله به مرحله ببینید.

حالا که transformedIngredients را داریم باید آن را نمایش دهیم. همیشه bread-top و bread-bottom را خواهیم داشت (همبرگر بدون نان وجود ندارد!) اما بین دو نان همبرگر transformedIngredients را خواهیم داشت:

    return (
        <div className={classes.Burger}>
            <BurgerIngredient type="bread-top" />
            {transformedIngredients}
            <BurgerIngredient type="bread-bottom" />
        </div>
    );

حالا اگر کدها را ذخیره کنید باید چنین همبرگری را ببینید:

همبرگر ما همراه مخلفاتش - state
همبرگر ما همراه مخلفاتش

در قسمت بعدی کنترل ingredients را به دست کاربر خواهیم داد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش ری اکت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.