Неправильно отрабатывает функция с циклом

Функция добавляет в корзину позиции. Проблема на моменте с проверкой, имеется ли в корзине такая же позиция, но с другим размером.

Код:

addCart(merch) {
  if(localStorage.getItem('cart')) {
    let array = JSON.parse(localStorage.getItem('cart'));

    for(let i = 0; i < array.length; i++) {
      if(merch.id === array[i].id && this.size === array[i].size) {
        array[i].count++
        localStorage.removeItem('cart')
        localStorage.setItem('cart', JSON.stringify(array));

      } else {
        let product = {
          id: merch.id,
          name: merch.real_name,
          image: merch.image,
          thumbnail: merch.thumbnail,
          price: merch.price,
          size: this.size,
          count: 1
        }

        array.push(product)
        localStorage.setItem('cart', JSON.stringify(array));
      }
    }
  } else {
    let array = []
    let product = {
      id: merch.id,
      name: merch.real_name,
      image: merch.image,
      thumbnail: merch.thumbnail,
      price: merch.price,
      size: this.size,
      count: 1
    }

    array.push(product)

    localStorage.setItem('cart', JSON.stringify(array));
  }
}

Пример того что мне нужно:

[
    {
       id: 0,
       name: Продукт 1,
       size: S,
       count: 2
    },
    {
       id: 1,
       name: Продукт 2,
       size: XS,
       count: 1
    }
]

А получаю:

[
    {
       id: 0,
       name: Продукт 1,
       size: S,
       count: 2
    },
    {
       id: 0,
       name: Продукт 1,
       size: S,
       count: 2
    },
    {
       id: 1,
       name: Продукт 2,
       size: XS,
       count: 1
    }
]

Вот тут можно посмотреть как ведет себя фунция https://playcode.io/


Ответы (1 шт):

Автор решения: SwaD

Цикл for не подходит для решения задачи по уникальноси элемента.

Если там 3 элемента с разным id, то даже если вы нашли нужный, цикл побежит дальше и внутри по else будет создавать вам новые элементы.

Так же вы мутируете массив при добавлении и ваш array.length увеличивается что создает новую итерацию цикла.

Вам необходимо брать сохраненный массив, осуществлять поиск по всему массиву и если нашли, увеличиваете, иначе добавляете

Вот примерный рабочий код с небольшой оптимизацией. Для поиска элемента в массиве, лучше всего подойдет метод find

  addCart(merch) {
    // Создаем массив
    const array = JSON.parse(localStorage.getItem('cart')) ?? [];
    // Если данные есть
    if(array.length) {
      // Ищем в массиве элемент с переданным id. Если найдтся, этот элемент будет возвращен
      const elem = array.find(item => item.id === merch.id && item.size === this.size);
      // Если нашли, увеличиваем
      if (elem) {
        elem.count++;
      } else { // если не нашли, пушим
        let product = {
          id: merch.id,
          name: merch.real_name,
          image: merch.image,
          thumbnail: merch.thumbnail,
          price: merch.price,
          size: this.size,
          count: 1
        }
        array.push(product);
      }
    } else {
      let product = {
        id: merch.id,
        name: merch.real_name,
        image: merch.image,
        thumbnail: merch.thumbnail,
        price: merch.price,
        size: this.size,
        count: 1
      }

      array.push(product)
    }
    // Сохраняем результат в хранилище
    localStorage.setItem('cart', JSON.stringify(array));
  }
UPD

Сокращенная функция(метод)

  addCart(merch) {
    const array = JSON.parse(localStorage.getItem('cart')) ?? [];
    const elem = array.find(item => item.id === merch.id && item.size === this.size);
    if (elem) {
      elem.count++;
    } else {
      let product = {
        id: merch.id,
        name: merch.real_name,
        image: merch.image,
        thumbnail: merch.thumbnail,
        price: merch.price,
        size: this.size,
        count: 1
      }
      array.push(product);
    }
    localStorage.setItem('cart', JSON.stringify(array));
  }
→ Ссылка