我在使用React的useContext钩子时遇到了麻烦。我正在尝试更新从上下文中获得的状态,但是我不知道如何操作。我设法更改了想要的对象的属性值,但每次运行此函数时最终都会添加另一个对象。这是我的一些代码:
“ CartItem”组件中的方法。
const addToQuantity = () => {
cartValue.forEach((item) => {
let boolean = Object.values(item).includes(props.name);
console.log(boolean);
if (boolean) {
setCartValue((currentState) => [...currentState, item.quantity++])
} else {
return null;
}
});
};
呈现“ CartItem”的“购物车组件”
const { cart, catalogue } = useContext(ShoppingContext);
const [catalogueValue] = catalogue;
const [cartValue, setCartValue] = cart;
const quantiFyCartItems = () => {
let arr = catalogueValue.map((item) => item.name);
let resultArr = [];
arr.forEach((item) => {
resultArr.push(
cartValue.filter((element) => item === element.name).length
);
});
return resultArr;
};
return (
<div>
{cartValue.map((item, idx) => (
<div key={idx}>
<CartItem
name={item.name}
price={item.price}
quantity={item.quantity}
id={item.id}
/>
<button onClick={quantiFyCartItems}>test</button>
</div>
))}
</div>
);
};
那么我如何保留我的cartValue数组中的先前对象,并且仍然在此类数组中的对象内部修改单个属性值?
编辑:这是ShoppingContext组件!
import React, { useState, createContext, useEffect } from "react";
import axios from "axios";
export const ShoppingContext = createContext();
const PRODUCTS_ENDPOINT =
"https://shielded-wildwood-82973.herokuapp.com/products.json";
const VOUCHER_ENDPOINT =
"https://shielded-wildwood-82973.herokuapp.com/vouchers.json";
export const ShoppingProvider = (props) => {
const [catalogue, setCatalogue] = useState([]);
const [cart, setCart] = useState([]);
const [vouchers, setVouchers] = useState([]);
useEffect(() => {
getCatalogueFromApi();
getVoucherFromApi();
}, []);
const getCatalogueFromApi = () => {
axios
.get(PRODUCTS_ENDPOINT)
.then((response) => setCatalogue(response.data.products))
.catch((error) => console.log(error));
};
const getVoucherFromApi = () => {
axios
.get(VOUCHER_ENDPOINT)
.then((response) => setVouchers(response.data.vouchers))
.catch((error) => console.log(error));
};
return (
<ShoppingContext.Provider
value={{
catalogue: [catalogue, setCatalogue],
cart: [cart, setCart],
vouchers: [vouchers, setVouchers],
}}
>
{props.children}
</ShoppingContext.Provider>
);
};
edit2:由于Diesel建议使用地图,我想出了实现此目的的代码!
const newCartValue = cartValue.map((item) => {
const boolean = Object.values(item).includes(props.name);
if (boolean && item.quantity < item.available) {
item.quantity++;
}
return item;
});
removeFromStock();
setCartValue(() => [...newCartValue]);
};```
答案 0 :(得分:0)
我假设您可以同时访问值和设置状态的能力:
const addToQuantity = () => {
cartValue.forEach((item) => {
let boolean = Object.values(item).includes(props.name);
console.log(boolean);
if (boolean) {
setCartValue((currentState) => [...currentState, item.quantity++])
} else {
return null;
}
});
};
现在...如果您执行[...currentState, item.quantity++]
,则将始终添加一个新项目。你什么都没改变。您还在每个项目上运行setCartValue
,这不是必需的。我不确定有多少可以更改,但是您似乎想更改值。这就是map
的优点。
const addToQuantity = () => {
setCartValue((previousCartValue) => {
const newCartValue = previousCartValue.map((item) => {
const boolean = Object.values(item).includes(props.name);
console.log(boolean);
if (boolean) {
return item.quantity++;
} else {
return null;
}
});
return newCartValue;
});
};
您获取所有值,进行所需的修改,然后可以将其设置为新状态。另外,它还创建了一个新数组,这很不错,因为它不会使您的数据发生变异。
此外,如果您知道只有一项会符合您的条件,请考虑使用.findIndex
方法,因为该方法在发现某物时会短路(它将在那里停止),然后修改该索引。