Issues
您在声明 React 组件时遇到问题,其中一些组件没有正确使用 props。function ItemDetail(handleClick) { ... }
应该function ItemDetail({ handleClick }) { ... }
, and const Discover = (props, params, handleClick) => { ... }
可能应该是这样的const Discover = ({ params, handleClick, ...props }) => { ... }
。 React 组件接收单个 props 对象参数。
handleChange
in App
也处于变异状态。
Solution
App
修复状态突变并确保 props 正确传递给路由组件。在检查添加到购物车时,使用商品 GUID 来搜索购物车,而不是浅层引用相等。更新购物车数量时,需要浅复制正在更新的购物车数组和购物车商品。尽可能使用功能状态更新,以确保它是从以前的状态更新的,而不是范围内关闭的任何陈旧状态值。
function App() {
const [show, setShow] = useState(true);
const [cart, setCart] = useState([]);
const handleClick = (item) => {
// Update cart item quantity if already in cart
if (cart.some((cartItem) => cartItem.productCode === item.productCode)) {
setCart((cart) =>
cart.map((cartItem) =>
cartItem.productCode === item.productCode
? {
...cartItem,
amount: cartItem.amount + 1
}
: cartItem
)
);
return;
}
// Add to cart
setCart((cart) => [
...cart,
{ ...item, amount: 1 } // <-- initial amount 1
]);
};
const handleChange = (productCode, d) => {
setCart((cart) =>
cart.flatMap((cartItem) =>
cartItem.productCode === productCode
? cartItem.amount + d < 1
? [] // <-- remove item if amount will be less than 1
: [
{
...cartItem,
amount: cartItem.amount + d
}
]
: [cartItem]
)
);
};
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="all-categories" element={<AllCategories />} />
<Route path="entertainment" element={<Entertainment />} />
<Route path="login" element={<Login />} />
<Route path="discover" element={<Discover />} />
<Route path="netflix" element={<Netflix />} />
<Route path="orders" element={<Orders />} />
<Route path="sign-up" element={<SignUp />} />
<Route path="products" element={<Products />} />
<Route
path="/itemDetail/:productCode/:value/:vendor"
element={<ItemDetail handleClick={handleClick} />}
/>
<Route
path="/Cart/"
element={(
<Cart
cart={cart}
setCart={setCart}
handleChange={handleChange}
/>
)}
/>
</Routes>
</Router>
);
}
项目详情
访问/破坏handleClick
正确支撑。传递该项目的productCode
到回调。
function ItemDetail({ handleClick }) {
const { productCode, vendor, value} = useParams();
const item = { productCode, vendor, value };
return (
<div>
<p>product id: {productCode}</p>
<p>price: {value}</p>
<p>vendor: {vendor}</p>
<button onClick={() => handleClick(item)}>Add to Cart</button>
</div>
);
}
Discover
正确访问/解构handleClick
打回来。使用Link
组件而不是原始锚点(<a />
) 标签。锚标记将重新加载应用程序,这很可能不是您想要发生的情况。根据代码我怀疑你实际上并不需要这个handleClick
自从ItemDetail
组件通过它并添加到购物车
import { Link } from 'react-router-dom';
const cardStyle = {
listStyle: "none",
margin: 5,
paddingLeft: 0,
minWidth: 240,
};
const Discover = () => {
const token = "not-the-actual-token";
const [result, setResult] = useState([]);
useEffect(() => {
fetch(
"https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
{
method: "GET",
headers: { Authorization: `Bearer ${token}` },
}
)
.then((res) => {
if (!res.ok) {
throw new Error('Network response was not OK');
}
return res.json();
})
.then((data) => setResult(data.result))
.catch(error => {
// handle any rejected Promises, errors, etc...
});
}, []);
return (
<div className="latestdeals container my-5">
<h1>All Products</h1>
<Row className="hotcards">
<Col className="colcard">
{result.map((item) => (
<div key={item.productCode} style={cardStyle}>
<Link to={`/itemDetail/${item.productCode}/${item.value}/${item.vendor}`}>
<StyledCard
name={item.vendor}
title={item.description}
price={item.value}
item={item}
/>
</Link>
</div>
))}
</Col>
</Row>
</div>
);
};
Cart
不要将购物车总计存储在状态中,它很容易从cart
state.
const Cart = ({ cart, setCart, handleChange }) => {
const handleRemove = (productCode) => {
setCart(cart => cart.filter(item => item.productCode !== productCode));
};
const price = cart.reduce((total, item) => total + item.amount * item.price, 0);
return (
<article>
{cart.map((item) => (
<div className="cart_box" key={item.id}>
<div>
<button onClick={() => handleChange(item.productCode, 1)}>+</button>
<button>{item.amount}</button>
<button onClick={() => handleChange(item.productCode, -1)}>-</button>
</div>
<div>
<span>{item.price}</span>
<button onClick={() => handleRemove(item.productCode)}>Remove</button>
</div>
</div>
))}
<div className="total">
<span>Total Price of your Cart</span>
<span>R - {price}</span>
</div>
</article>
);
};