تکمیل دکمه های checkout + کار با URLSearchParams

08 اسفند 1398
تکمیل دکمه های checkout + کار با URLSearchParams

تکمیل دکمه های checkout

اگر از قسمت قبل به یاد داشته باشید ما کدهای دکمه های CANCEL و CONTINUE را تکمیل نکردیم:

<Button
    btnType="Danger"
    clicked> CANCEL </Button>
<Button
    btnType="Success"
    clicked> CONTINUE </Button>

در حال حاضر checkoutSummary یک کامپوننت کاربردی است و من می توانم آن را به یک کامپوننت کلاس-محور تبدیل کنم و سپس این دو دکمه را در همین جا مدیریت کنم اما فکر می کنم زحمت این کار از زحمت پاس دادن prop ها بیشتر باشد بنابراین می گوییم:

<Button
    btnType="Danger"
    clicked={props.checkoutCancelled}> CANCEL </Button>
<Button
    btnType="Success"
    clicked={props.checkoutContinued}> CONTINUE </Button>

من قرار است دو تابع را از طریق props به این دو دکمه پاس بدهم که البته هنوز آن ها را تعریف نکرده ایم. برای تعریف آن ها وارد کامپوننت Checkout.js شوید چرا که کامپوننت اصلی برای checkout همان Checkout.js می باشد. در قسمت JSX این فایل می گوییم:

return (
    <div>
        <CheckoutSummary
        ingredients={this.state.ingredients} 
        checkoutCancelled={}
        checkoutContinued={}                
        />
    </div>
);

حالا که این دو prop را به CheckoutSummary پاس داده ایم باید خودشان را تعریف کنیم. خارج از تابع render و پایین تر از state می گویم:

checkoutCancelled = () => {
        
}

checkoutContinued = () => {

}

ابتدا با تکمیل کردن کدهای checkoutCancelled شروع می کنیم:

checkoutCancelled = () => {
    this.props.history.goBack();
}

اگر یادتان باشد کامپوننت Checkout با استفاده از <Route> ها بارگذاری می شود بنابراین درون آن ها به prop های routing نیز دسترسی داریم. ما با استفاده از همین prop ها و متد goBack کاربر را به صفحه ی قبل می بریم. متد ()goBack یکی از متدهایی است که درون شیء history قرار دارد و کاربر را به صفحه ی قبل هدایت می کند. برای متد checkoutContinued هم می گوییم:

checkoutContinued = () => {
    this.props.history.replace('checkout/contact-data');
}

بنابراین اگر کاربر روی دکمه ی CONTINUE کلیک کند به مسیر checkout/contact-data می رود. توجه داشته باشید که ما هنوز این path را تعریف نکرده ایم و چیزی به نام contact-data نداریم اما در آینده آن را تعریف خواهیم کرد.

در نهایت به سادگی آن ها را به عنوان prop به کامپوننت CheckoutSummary پاس می دهیم:

return (
    <div>
        <CheckoutSummary
            ingredients={this.state.ingredients}
            checkoutCancelled={this.checkoutCancelled}
            checkoutContinued={this.checkoutContinued}
        />
    </div>
);

حالا اگر به مرورگر برویم و خودمان را به صفحه ی checkout برسانیم دو گزینه برای انتخاب داریم:

  • CONTINUE
  • CANCEL

با کلیک روی CANCEL به صفحه ی قبل که همان صفحه ی ساخت همبرگر است منتقل می شویم و با کلیک روی CANCEL آدرس مرورگر به http://localhost:3000/checkout/contact-data تبدیل می شود اما در ظاهر مرورگر هیچ تغییری را مشاهده نخواهیم کرد چرا که هنوز هیچ کدی برای مدیریت این مسیر خاص ننوشته ایم. این یعنی کد ما به درستی عمل می کند.

در حال حاضر برنامه ی ما یک مشکل دارد و آن این است که کامپوننت checkout از داده های واقعی استفاده نمی کند؛ اگر من یک همبرگر سفارش بدهم که اطلاعات زیر را داشته باشد:

  • Bacon: 0
  • Cheese: 1
  • Meat: 1
  • Salad: 0

پس از کلیک روی CONTINUE و انتقال به صفحه ی checkout هیچ شباهتی بین برگر نمایش داده شده و همبرگر من وجود ندارد. در واقع همبرگر نمایش داده شده در checkout یک همبرگر پیش فرض و ساده است و همبرگر واقعی که سفارش داده شده را نمایش نمی دهد. باید این مشکل را حل کنیم.

کار با URLSearchParams

قبل از پرداختن به حل این مشکل باید با موضوعی به نام URLSearchParams آشنا شوید (گرچه که این مورد ربطی به React ندارد و جاوا اسکریپت عادی است که شما باید بلد باشید). من در این جلسه شما را با URLSearchParams آشنا می کنم.

یکی از مهم ترین کارها در توسعه ی front-end مدیریت query string یا query parameter ها است. اگر یک جست و جوی ساده در npm داشته باشید با انبوهی از پکیج ها مواجه می شوید که قرار است این مشکل را حل کنند اما اکثر کاربران نمی دانند که یک API جدید برای کار با query string ها وجود دارد که به نام URLSearchParams شناخته می شود. پشتیبانی مرورگرها از این API نیز بسیار عالی است و از ال 2016 به بعد پشتیبانی کامل پیاده سازی شده است.

URLSearchParams به عنوان پارامتر یک query string می گیرد (چه با علامت ؟ و چه بدون آن). اگر شما دوست دارید که تمام URL خود را به آن بدهید تا خودش پارامتر های query string را جدا کند باید از location.search استفاده کنید. فرض کنید ما یک URL کامل به شکل زیر داشته باشیم:

buy-shirts-here.com/filter?size=M&colour=red&sleeves=short

مقدار location.search برای این URL برابر با مقدار زیر خواهد بود:

?size=M&colour=red&sleeves=short

بنابراین می توانیم یک instance از URL خود بسازیم:

const url = new URL("https://buy-shirts-here.com/filter?filter?size=M&colour=red&sleeves=short")

سپس از دستور url.search استفاده کنیم که مقدار زیر را برمی گرداند:

?size=M&colour=red&sleeves=short

هر دو روش بدون مشکل هستند بنابراین راحت ترین روش به صورت زیر است:

const params = new URLSearchParams(location.search)

موارد و توابع کار با این API بسیار زیاد هستند که با مراجعه به صفحه ی توسعه دهندگان موزیلا با آن ها آشنا خواهید شد اما من مهم ترین موارد آن را ذکر می کنم. به طور مثال دستور has به شما می گوید که آیا پارامتر مورد نظر شما در URL موجود است یا خیر:

params.has('size') // => true
params.has('button-style') // => false

برای خواندن مقدار یک پارامتر می توانید از get استفاده کنید. اگر پارامتر شما در کوئری موجود نباشد مقدار null به شما برگردانده خواهد شد:

params.get('size') // => 'M'
params.get('button-style') // => null

البته باید حواستان به مورد خاصی نیز باشد. برخی از پارامتر های query string ها چندین مقدار دارند. به طور مثال به URL زیر نگاه کنید:

// URL: buy-shirts-here.com/filter?size=M&size=L

در این URL یک پارامتر به نام size داریم که دو بار تکرار شده است یا به عبارت دیگر دو مقدار دارد. اگر در چنین حالتی از get استفاده کنید فقط مورد اول را به شما برمیگرداند و اگر می خواهید تمام مقادیر را به دست بیاورید باید از getAll استفاده کنید تا تمام مقادیر به شکل یک آرایه به شما برگردانده شود:

// URL: buy-shirts-here.com/filter?size=M&size=L
const params = new URLSearchParams(location.search)
params.get('size') //=> 'M'
params.getAll('size') //=> ['M', 'L']

همچنین اگر می خواهید بین پارامترها گردش کنید باید از ساختار خاص for of استفاده کنید. به مثال زیر توجه کنید:

// URL: buy-shirts-here.com/filter?size=M&size=L&colour=red
const params = new URLSearchParams(location.search)
for (let p of params) {
  console.log(p)
}
// => ['size', 'M']
// => ['size', 'L']
// => ['colour', 'red']

Let ای که تعریف کرده ایم (p) نماینده ی هر پارامتر خواهد بود. خروجی این console.log را به صورت کامنت در کد بالا برایتان قرار داده ام.

نکته ی مهم دیگر استفاده از سه دستور زیر است:

  • ()Keys که کلید های هر پارامتر را به شما بر می گرداند.
  • ()Values که مقادیر هر پارامتر را به شما بر می گرداند.
  • ()entries که کلید ها و مقادیر را به صورت یک جفت آرایه ای به شما بر می گرداند.

به مثال زیر دقت کنید:

// URL: buy-shirts-here.com/filter?size=M&size=L&colour=red
const params = new URLSearchParams(location.search)
console.log([...params.keys()]) // => ['size', 'size', 'colour']
console.log([...params.values()]) // => ['M', 'L', 'red']
console.log([...params.entries()]) // => [['size', 'M'], ['size', 'L'], ['colour', 'red']]

خروجی هر دستور را به صورت یک کامنت برایتان قرار داده ام تا متوجه نوع کار هر کدام بشوید.

متدهای بسیار زیادی برای کار با این API وجود دارد (مثل append و delete و toString و...) که تمامی آن ها در صفحه ی توسعه دهندگان موزیلا موجود است و می توانید به سادگی آن ها را مطالعه کنید. من این مقدمه را برایتان توضیح دادم تا در جلسه ی بعد به سراغ مدیریت query parameter ها برویم. در واقع برای داشتن یک همبرگر واقعی در checkout باید مقادیر سفارش داده شده را به صورت query string به کامپوننت checkout پاس داده و آن ها را دریافت کنیم.

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

دیدگاه‌های شما

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