检查购物车中的重复项并更新数量 (ReactJS)

Check for duplicates in a shopping cart and updating the quantity (ReactJS)

我有一个购物车,它是一个嵌套列表。我想在再次添加之前检查某个项目是否已经在列表中。如果它已经在列表中,我只想更新数量。我在这里做错了什么,我怎么能在这里实现本地存储(假设)

函数如下:

   function addToCart(e) {
    var updatedCart = [];
    if (cart.includes(e.target.innerText)) {
    console.log("Duplicate found");
    for (var i = 0; i < cart.length; i++) {
        if (cart[i][0] == e.target.innerText) {
        cart[i][1]++;
        updatedCart.push(cart[i]);
        i++;
        } else {
        i++;
        }
    }
    } else {
    setCart((cart) => [...cart, [e.target.innerText, 1]]);
    }
}

作为一个建议,最好(在时间复杂度方面)将购物车之类的东西存储在 javascript 对象或地图中。您可以将项目名称(最好有某种唯一 ID)存储为键,将项目金额存储为值;所以基本上是这样的:

const cart = {
  itemA: 1,
  itemB: 2,
  itemC: 4
}

这样你就可以通过复制旧状态来更新值,并且只覆盖搜索到的键值(如果存在)

const cartCopy = {...cart};
if (!cartCopy[itemName]) {
  cartCopy[itemName] = 1;
} else {
  cartCopy[itemName] += 1;
}
setState(cartCopy);

您应该自己改进该代码并使用此代码段作为一些快速提示,因为使用 localStorage 并不难。特别是使用这种对象的方式;只是提醒一下,localStorage 访问速度很慢,所以我建议先更新组件的状态,更新时只需将带有某种标签的对象添加到 localStorage 中。你应该只使用 localStorage 来让你的购物车在会话中保持某种持久性,所以基本上你只会在你安装应用程序时从 localStorage 加载状态(如果购物车始终可见)并在有一些时更新 localStorage更新到您购物车的本地状态。

基于行:

setCart((cart) => [...cart, [e.target.innerText, 1]]);

我可以假设,您的 cart 包含数组 个数组 ,其中内部数组的产品名称和数量作为其第一项和第二项,分别。

如果我的假设是正确的,则条件:

if (cart.includes(e.target.innerText))

从未遇到过,因此相应的块从未执行过。

我可能建议的另一件事是使用 textContent 而不是 innerText(对于 performance considerations)。

因此,您的 addToCart() 函数可能类似于:

const addToCart = ({target:{textContent:itemName}}) => {
    const cartShallowCopy = [...cart],
            matchingItem = cartShallowCopy.find(([cartItemName]) =>
                cartItemName == itemName)
    matchingItem
        ? matchingItem[1]++
        : cartShallowCopy.push([itemName, 1])
    setCart(cartShallowCopy)
}

以下是概念验证现场演示:

const { useState } = React,
      { render } = ReactDOM,
      rootNode = document.getElementById('root')
      
const App = () => {
  const [cart, setCart] = useState([]),
        addToCart = ({target:{textContent:itemName}}) => {
           const cartShallowCopy = [...cart],
                 matchingItem = cartShallowCopy.find(([cartItemName]) =>
                     cartItemName == itemName)
           matchingItem
             ? matchingItem[1]++
             : cartShallowCopy.push([itemName, 1])
           setCart(cartShallowCopy)
        }
  return (
    <div>
      <h4>These are products:</h4>
      <ul>
        {
          ['apple', 'banana', 'pear', 'peach'].map(name => (
            <li key={name}>
              <span 
                onClick={addToCart}
                className="productItem"
              >
                {name}
              </span>
            </li>
          ))
        }
      </ul>
      <h4>This is cart:</h4>
      <ul>
        { !!cart.length && cart.map(([name, qty]) => (
            <li key={name}>{name}, {qty}</li>
          ))
        }
      </ul>
    </div>
  )
}

render (
  <App />,
  rootNode
)
.productItem:hover {
  cursor: pointer;
  background-color: purple;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

或者基本上,只使用 Map。也有助于性能优化。 您的购物车结构将是这样的:

{
  productId1:quantity1,
  productId2:quantity2,
  ...
  ..
}

一个小片段:

      let map = new Map(state.cart);
      let qty = (map.get(id) || 0) + quantity; //if item is not present will just add the item, else update its quantity
      if (qty !== 0) {
        map.set(id, qty);
      } else {
        map.delete(id); //else delete the item from cart
      }