Chupachar
@Chupachar
front-end dev

Почему localStorage.getItem(key) отрабатывает только после второго клика?

Всем добрый вечер, уже достаточно давно не могу решить данную задачу:
В примере https://jsfiddle.net/fytv3rku/2/
есть некоторое количество блоков с инпутами value которых мы вписываем и по клику на click суммируем. Суммируются как value дочерних инпутов родительского кликнутого блока, так и сумма инпутов второго блока тоже складывается с предыдущей суммой, в общем обычный reduce. По факту, мне просто нужно получить общую сумму абсолютно всех value инпутов. Так же я сохраняю значения инпутов в локальном хранилище для отрисовки в разметку и сохранению значения после перезагрузки. В песочнице всё хорошо работает и можно вывести в консоль общую сумму по клику сразу же по после перезагрузки страницыconsole.log(accommodationSum)
Проблема в том, что в моём проекте по какой то причине при первом клике на 'click' reduce возвращает 0, то есть initialValue, а на втором клике уже всё отрабатывает по инструкции, то есть предположим что в локальном хранилище находится такая сумма:
key = [{sum: 12}],
то после перезагрузки в моём проекте выведется 0 как сумма (console.log('sum: ', sum)), при key.reduce((acc, curr) => acc + curr.sum, 0) хотя curr.sum по факту равен 12 и уже при втором клике выводит актуальное значение. Я долго разбирался и пришел в выводу что это из за того, скорее всего, что у меня getItem находится в глобальной области видимости и что то мешает reduce нормально отрабатывать, но в песочнице почему то работает. Так же в reduce при первом клике приходит заполненный массив, не пустой и почему initialValue отрабатывает не понятно. Извините за сумбур, накипело.
<div class="cart">
  <input type="text" class="amount-one" value="0">
  <input type="text" class="amount-two" value="0">
  <input type="text" class="amount-three" value='0'>
  <button>click</button>
</div>
<div class="cart">
  <input type="text" class="amount-one" value="0">
  <input type="text" class="amount-two" value="0">
  <input type="text" class="amount-three" value='0'>
  <button>click</button>
</div>

<div class="info"></div>

const currentTariff = JSON.parse(localStorage.getItem("cabins") || "[]");
    const btn = document.querySelectorAll('button')
    const info = document.querySelector('.info')

    const render = (tariff = currentTariff) => {
      [...tariff].forEach((el) => {
        info.insertAdjacentHTML(
          "beforeend",
          `<div>${el.accommodation}</div>`)
      })
    }
    render()

    btn.forEach((button) => {
      button.addEventListener("click", function(e) {
        const cart = e.target.closest(".cart");
        const countOne = cart.querySelector(".amount-one").value;
        const countTwo = cart.querySelector(".amount-two").value;
        const countThree = cart.querySelector(".amount-three").value;

        const accommodationPass = //переменных статичное количество, поэтому без reduce
          parseInt(countOne) +
          parseInt(countTwo) +
          parseInt(countThree);

        const obj = {
          countOne: countOne,
          countTwo: countTwo,
          countThree: countThree,
          accommodation: parseInt(accommodationPass),
        }

        currentTariff.push(obj);
        render([obj]);
        updateState()

        const accommodationSum = currentTariff.reduce(
          (acc, curr) => acc + curr.accommodation,
          0
        );
        console.log(accommodationSum)
      })

      function updateState() {
        localStorage.setItem("cabins", JSON.stringify(currentTariff));
      }
    })
  • Вопрос задан
  • 224 просмотра
Решения вопроса 1
ae_ph
@ae_ph
I'm a owl )
Я исправил данный кода, теперь это должно работать для вас.
Вот пример на CodePen
Тот-же код, что и на codepen...

HTML
<div class="container">
  <div class="cart">
    <input class="input amount-one" type="text" value="0" />
    <input class="input amount-two" type="text" value="0" />
    <input class="input amount-three" type="text" value="0" />
    <button class="btn">click</button>
  </div>
  <div class="cart">
    <input class="input amount-one" type="text" value="0" />
    <input class="input amount-two" type="text" value="0" />
    <input class="input amount-three" type="text" value="0" />
    <button class="btn">click</button>
  </div>
  <div class="box">
    <input id="clear" type="button" value="clear all" />
    <div class="info"></div>
  </div>
</div>


CSS
body {
  display: flex;
  justify-content: center;
  background-color: #1d1e22;
}
.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.cart {
  display: flex;
  flex-direction: column;
  margin: 20px;
}
.input {
  padding-left: 20px;
  height: 20px;
  margin-bottom: 5px;
  font-size: 20px;
  border-radius: 10px;
}
.btn {
  height: 30px;
  font-size: 20px;
  border-radius: 10px;
}
.box {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 20px;
}
#clear {
  width: 100px;
  height: 40px;
  margin-bottom: 10px;
  font-size: 20px;
  border-radius: 10px;
}
.info {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 200px;
  height: 30px;
  border: 2px solid #bbb;
  background-color: #fff;
}


JavaScript
let currentTariff = JSON.parse(localStorage.getItem('cabins') || '[]');
const passengersMax = 3; // Максимальное количество пассажиров
let accommodationSum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
const btn = document.querySelectorAll('.btn');
const info = document.querySelector('.info');

// Вывести текущие тарифные данные в информационный блок
const render = (tariff = currentTariff) => {
  [...tariff].forEach(el => {
    info.insertAdjacentHTML('beforeend', `<div>${el.accommodation}</div>`);
  });
};
render();

btn.forEach(button => {
  button.addEventListener('click', function (e) {
    const cart = e.target.closest('.cart');
    const countOne = cart.querySelector('.amount-one').value;
    const countTwo = cart.querySelector('.amount-two').value;
    const countThree = cart.querySelector('.amount-three').value;
    const accommodationPass = parseInt(countOne) + parseInt(countTwo) + parseInt(countThree);

    if (accommodationSum + accommodationPass > passengersMax) {
      alert('В этом заказе вы превысили максимальное количество человек');
      return;
    }

    const obj = {
      countOne: countOne,
      countTwo: countTwo,
      countThree: countThree,
      accommodation: parseInt(accommodationPass),
    };

    // Обновляем текущий тариф и отображаем новые данные
    currentTariff.push(obj);
    updateState();

    const sum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
    info.innerHTML = `<div>Общая сумма: ${sum}</div>`;

    accommodationSum = sum; // Устанавливаем сумму размещения на текущую сумму
  });

  function updateState() {
    localStorage.setItem('cabins', JSON.stringify(currentTariff));
  }
  // Очищаем входы и информационный блок при нажатии кнопки "clear all"
function clearData() {
    currentTariff.length = 0;
    localStorage.removeItem('cabins');
    info.innerHTML = '';
    const inputs = document.querySelectorAll('input[type="text"]');
    inputs.forEach(input => {
      input.value = 0;
    });
    accommodationSum = 0;  // Сбрасываем сумму размещения до 0
}

  const clearBtn = document.querySelector('input#clear');
  clearBtn.addEventListener('click', clearData);
});
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы