我正试图使购物车产生反应,并希望每次点击都能增加商品的数量。我可以找到的所有示例都只是将一个新项目推送到数组,而不是增加现有项目的数量,结果是:
[
{id: 1, item: pants, qty: 1},
{id: 1, item: pants, qty: 1},
{id: 2, item: shirt, qty: 1}
]
当我的目标是:
[
{id: 1, item: pants, qty: 2},
{id: 2, item: shirt, qty: 1}
]
我提出了以下可行的方法,但它非常难看。我在寻找更优雅的东西。
function App() {
const [items, setItems] = useState([]);
const updateState = (item) => (e) => {
let newArray = [...items];
if (items.some((el) => el.id === item.id)) {
const place = items.findIndex((obj) => obj.id === item.id);
newArray[place] = {
id: item.id,
item: item.name,
qty: items[place].qty + 1,
};
} else {
newArray.push({ id: item.id, item: item.name, qty: 1 });
}
console.log(newArray);
setItems(newArray);
};
return (
<div>
<button onClick={updateState({ id: 1, name: 'pants' })}></button>
<button onClick={updateState({ id: 2, name: 'shirt' })}></button>
</div>
);
}
这是有效的丑陋版本的代码沙箱。 https://codesandbox.io/s/billowing-resonance-f1ip6?file=/src/App.js
答案 0 :(得分:0)
您做对了。最终会有一些库可以帮助您使代码更漂亮,例如DotProp,但它只会处理您在后台所做的事情。
最终,您可以通过直接获取indexOf并检查if语句中是否未定义indexOf来避免执行.some(...)
,
答案 1 :(得分:0)
您的实现很好,但是为了保持整洁,我认为您应该创建一个新函数,该函数接受数组和项目,如果尚不存在则插入该项目,或者如果该项目存在则更新项目的数量在数组中。
这是另一种实现方式。
const arr = [
{id: 1, item: "pants", qty: 1},
{id: 2, item: "shirt", qty: 1}
]
const addItem = (arr, item) => {
const idx = arr.findIndex(el => el.id === item.id);
if (idx === -1) {
return [...arr, item]
}
arr[idx] = {...arr[idx], qty: arr[idx].qty + 1}
return [...arr];
}
let newArr = addItem(arr, {id: 1, item: "pants", qty: 1})
newArr = addItem(newArr, {id: 3, item: "jeans", qty: 1})
console.log(newArr)
答案 2 :(得分:0)
我认为这并不难看。你可以尝试吗?
import React from "react"
import "./styles.css"
export default function App() {
const [items, setItems] = React.useState([
{id: 1, name: 'pants'},
{id: 2, name: 'shirt'}
])
const handleClick = (i) => {
setItems(items.map((item, curIndex) =>
i === curIndex ? { ...item, qty: ++item.qty||1 } : item
))
}
return (
<div>
{items.map((item,index)=>(
<button onClick={()=>handleClick(index)}>{item.qty || 0}</button>
))}
</div>
)
}