检查购物车中的重复项并更新数量 (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
}
我有一个购物车,它是一个嵌套列表。我想在再次添加之前检查某个项目是否已经在列表中。如果它已经在列表中,我只想更新数量。我在这里做错了什么,我怎么能在这里实现本地存储(假设)
函数如下:
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
}