Почему промежуточный итог не суммируется друг с другом?

#javascript #reactjs #react-redux

#javascript #reactjs #реагировать-redux

Вопрос:

 import React, { useEffect } from "react";
import { addToCart, removeFromCart } from "../actions/cartActions";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
function CartScreen(props) {
  const cart = useSelector((state) => state.cart);

  const { cartItems } = cart;

  const productId = props.match.params.id;
  const qty = props.location.search
    ? Number(props.location.search.split("=")[1])
    : 1;
  const dispatch = useDispatch();
  const removeFromCartHandler = (productId) => {
    dispatch(removeFromCart(productId));
  };
  useEffect(() => {
    if (productId) {
      dispatch(addToCart(productId, qty));
    }
  }, []);

  const checkoutHandler = () => {
    props.history.push("/signin?redirect=shipping");
  };

  return (
    <div className="cart">
      <div className="cart-list">
        <ul className="cart-list-container">
          <li>
            <h3>Shopping Cart</h3>
            <div>Price</div>
          </li>
          {cartItems.length === 0 ? (
            <div>Cart is empty</div>
          ) : (
            cartItems.map((item) => (
              <li>
                <div className="cart-image">
                  <img src={item.image} alt="product" />
                </div>
                <div className="cart-name">
                  <div>
                    <Link to={"/product/"   item.product}>{item.name}</Link>
                  </div>
                  <div>
                    Qty:
                    <select
                      value={item.qty}
                      onChange={(e) =>
                        dispatch(addToCart(item.product, e.target.value))
                      }
                    >
                      {[...Array(item.countInStock).keys()].map((x) => (
                        <option key={x   1} value={x   1}>
                          {x   1}
                        </option>
                      ))}
                    </select>
                    <button
                      type="button"
                      className="button"
                      onClick={() => removeFromCartHandler(item.product)}
                    >
                      Delete
                    </button>
                  </div>
                </div>
                <div className="cart-price">${item.price}</div>
              </li>
            ))
          )}
        </ul>
      </div>
      <div className="cart-action">
        <h3>
          Subtotal ( {cartItems.reduce((a, c) => a   c.qty, 0)} items) : ${" "}
          {cartItems.reduce((a, c) => a   c.price * c.qty, 0)}
        </h3>
        <button
          onClick={checkoutHandler}
          className="button primary full-width"
          disabled={cartItems.length === 0}
        >
          Proceed to Checkout
        </button>
      </div>
    </div>
  );
}

export default CartScreen;
 

Основная цель этого кода — отобразить веб-страницу по имени экрана корзины.
Внутри экрана корзины находятся все товары, которые я хочу купить с другой страницы, взятые из другого js-файла, в котором указаны все даты для этих товаров.

Я хочу выделить этот конкретный код прямо здесь.

 <h3>
Subtotal ( {cartItems.reduce((a, c) => a   c.qty, 0)} items) : ${" "}
{cartItems.reduce((a, c) => a   c.price * c.qty, 0)}
</h3>
 

Способ работы этого кода:
Промежуточный итог подсчитывает, сколько всего товаров у меня есть в корзине, а затем берет стоимость каждого продукта и умножает ее на их количество, прежде чем добавлять все и сообщать мне, сколько стоит все, что я хочу купить, прежде чем я захочу это купить. Раздел «Общая цена» работает абсолютно нормально.

Что меня озадачивает, так это то, что промежуточный итог количества товаров в корзине, похоже, не работает так, как я намереваюсь.

Это работает нормально, если у меня просто есть 2 отдельных товара в корзине, из которых я хочу купить 1, в котором промежуточный итог сообщает мне, что у меня в общей сложности 2 товара в корзине, что правильно. Но как только я хочу купить 2 из одного элемента, промежуточный итог каким-то образом превращается из предыдущего утверждения 2 item в 12 или, скорее, 1 для одного элемента и 2 для другого элемента, который я хочу купить 2. По какой-то причине они не объединяются, когда они должны показывать 3, а не 12.

Ответ №1:

Убедитесь, что ваши qty price свойства и являются не строками, а числами. Если вы сохраните эти значения в виде чисел, ваши .reduce() методы будут работать должным образом:

 const cartItems = [
  { qty: 1, price: 5.99 },
  { qty: 2, price: 25.0 },
  { qty: 5, price: 10.0 },
];

cartItems.reduce((a, c) => a   c.qty, 0); 
// => 8

cartItems.reduce((a, c) => a   c.price * c.qty, 0);
// => 105.99
 

Если вы используете оператор с числами, он суммирует их, как и следовало ожидать. Однако, если вы сохраните свои числа в виде строк и попытаетесь вычислить их сумму, это фактически объединит их в новую строку.

Если вы используете * оператор, вы неявно преобразуете строки в числа, и именно поэтому общая цена работает, а общее количество элементов — нет:

 const cartItems = [
  { qty: '1', price: '5.99' },
  { qty: '2', price: '25.00' },
  { qty: '5', price: '10.00' },
];

cartItems.reduce((a, c) => a   c.qty, 0);
// => "0125"

cartItems2.reduce((a, c) => a   c.price * c.qty, 0);
// => 105.99
 

Чтобы исправить это, вам нужно либо убедиться, что вы сохраняете qty и price как числа, либо преобразовать их в свой .reduce() .

 const cartItems = [
  { qty: '1', price: '5.99' },
  { qty: '2', price: '25.00' },
  { qty: '5', price: '10.00' },
];

cartItems.reduce((a, c) => a   Number(c.qty), 0);
// => 8