استفاده از Query parameter ها در checkout.js

22 بهمن 1399
استفاده از Query parameter ها در checkout.js

استفاده از Query parameter ها در checkout.js

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

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

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

برای حل این مشکل باید به BurgerBuilder.js و تابع purchaseContinueHandler برویم. در حال حاضر این تابع فقط کد زیر را دارد:

this.props.history.push('/checkout');

این کد باید ویرایش شود و به جای checkout/ یک شیء جاوا اسکریپتی بگیرد. ابتدا یک ثابت به نام queryParams میسازیم که در ابتدا یک تابع خالی است:

const queryParams = [];

حالا عناصر همبرگر را تک به تک به این آرایه اضافه می کنیم:

const queryParams = [];
for (let i in this.state.ingredients) {
    queryParams.push(encodeURIComponent(i) + '=' + encodeURIComponent(this.state.ingredients[i]));
}

ما در اینجا از یک حلقه ی for استفاده کرده و مقادیر را یک به یک به queryParams اضافه کرده ایم. مطمئن هستم که ساختار کوئری ها را می دانید:

?prop=value&prop=value

تابع encodeURIComponent از توابع جاوا اسکریپتی است که به ما اجازه می دهد مقادیر خودمان را به نوعی تبدیل کنیم که بتواند در URL قرار بگیرد. مثلا هیچ URL ای نمی تواند حروف فارسی یا اسپیس بگیرد اما تابع encodeURIComponent این اسپیس (یا هر کاراکتر غیر قانونی دیگری) را تبدیل به یک کاراکتر قابل قبول می کند. البته در برنامه ی ما نیازی به این کار نیست چرا که از کاراکتر هایی مثل اسپیس و... استفاده نمی کنیم اما کار از محکم کاری عیب نمی کند!

قسمت اول این کد encodeURIComponent به ما خصوصیت مربوطه (مثلا salad) را می دهد. سپس = را گذاشته ایم (به خاطر ساختار کوئری ها) و سپس مقدار آن خصوصیت (مثلا 2 یا 3 یا هر مقداری) را قرار داده ایم. در نهایت باید مقادیر خود را با & به هم بچسبانیم (به ساختار کوئری ها که بالاتر ذکر کردم دقت کنید) بنابراین می گوییم:

const queryParams = [];
for (let i in this.state.ingredients) {
    queryParams.push(encodeURIComponent(i) + '=' + encodeURIComponent(this.state.ingredients[i]));
}
const queryString = queryParams.join('&');

حالا باید دستور push را بنویسیم:

const queryParams = [];
for (let i in this.state.ingredients) {
    queryParams.push(encodeURIComponent(i) + '=' + encodeURIComponent(this.state.ingredients[i]));
}
const queryString = queryParams.join('&');

this.props.history.push({
    pathname: '/checkout',
    search: '?' + queryString
});

دلیل اضافه کردن علامت سوال همان ساختاری است که بالاتر توضیح دادم. حالا اگر به مرورگر برویم و یک سفارش ثبت کنیم، آدرس URL ما به شکل زیر خواهد بود:

http://localhost:3000/checkout?bacon=1&cheese=0&meat=1&salad=0

بنابراین کارمان را درست انجام داده ایم اما حالا باید این مقادیر را در checkout.js دریافت کنیم بنابراین به checkout.js بروید و این کار را در componentDidMount انجام دهید:

componentDidMount() {
    const query = new URLSearchParams(this.props.location.search);

}

در اینجا یک ثابت به نام query ایجاد کرده ام و درون آن از constructor مربوط به URLSearchParams استفاده کرده ام. URLSearchParams از اشیاء پیش فرض جاوا اسکریپت است که به شما کمک می کند با query string های URL کار کنید (برای اطلاعات بیشتر به این صفحه مراجعه کنید). برای پارامتر این constructor نیز از شیء location استفاده کرده ام تا به query string های درون URL دسترسی داشته باشم. به زبان ساده تر ثابت query دارای قسمت query string ما می باشد، یعنی این قسمت:

?bacon=1&cheese=0&meat=1&salad=0

حالا می گوییم:

componentDidMount() {
    const query = new URLSearchParams(this.props.location.search);
    const ingredients = {};
    for (let param of query.entries()) {
        // ['salad', '1']
        ingredients[param[0]] = +param[1];
    }
    this.setState({ ingredients: ingredients });
}

یک شیء خالی به نام ingredients ساخته ایم. سپس از یک حلقه ی for استفاده کرده ایم تا بین پارامتر های query string گردش کنیم. من در جلسه ی قبل مثالی از استفاده از entries برایتان آورده بودم که شامل سه دستور مهم برای کار با این پارامتر ها بود:

  • ()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']]

همانطور که می بینید entries هر پارامتر را به همراه value اش در قالب یک آرایه به ما می دهد. مثلا:

['size', 'M']

اولین عضو این آرایه با ایندکس صفر همان size و دومین عضو با ایندکس 1 همان M (مقدار پارامتر) است. ما بر همین اساس کد زیر را نوشته ایم:

componentDidMount() {
    const query = new URLSearchParams(this.props.location.search);
    const ingredients = {};
    for (let param of query.entries()) {
        // ['salad', '1']
        ingredients[param[0]] = +param[1];
    }
    this.setState({ ingredients: ingredients });
}

برای هر پارامتر که به صورت یک آرایه به ما برگردانده می شود (چرا که از entries استفاده کرده ایم) ایندکس صفر همان پارامتر و ایندکس 1 مقدار آن پارامتر است. علامت مثبتی که کنار [1]param+ گذاشته ایم برای تبدیل کردن رشته به عدد استفاده می شود و یک راه میانبر در جاوا اسکریپت است. در نهایت نیز مقدار state جدید را به همین صورت تنظیم کرده ایم.

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

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