好的,我现在正在用Redux和Typescript写一个React应用程序,但是我很难找到一个问题的解决方案,因为我对Redux还很陌生。这是一个餐馆在线订单页面,我在Order.tsx页面中有两个组件(MenuItems.tsx和Cart.tsx),还有一个Rootreducer.tsx,它包含了我所有的菜单信息、我的根还原器和商店:
页面上垂直黑线的左边是MenuItems.tsx组件中的所有内容,右边是Cart.tsx组件。当我单击Add To Cart时,食物被推送到我所在州的items[]数组中,并显示在购物车中。
问题是,当我在一个部分中的任何项目上单击“添加到购物车”时,它返回该部分中的每个食品项目,或者action.payload包含的整个数组(目前它将有效负载中的所有5个食品名称及其价格发送到Cart组件中)。虽然它是工作代码,但我特别希望它能够在我单击某个特定食品上的按钮时,我只想让购物车显示那一个项目,而不是所有5餐在Starters部分。
正在访问的我的初始菜单数据:
const initialMenu = [
{
section: "Starters",
list: [
{
img: chickenwings,
name: "Chicken Pub Wings",
desc: "Served with blue cheese dip and celery sticks. Choose your style plain and crispy, mild sticky barbecue or hot spicy Louisiana sauce",
price: "$9 for 6 wing basket, $14 for 12 wing basket",
},
{
img: soupoftheday,
name: "Soup of the Day",
desc: "Served with Dublin Soda Bread",
price: "$6",
},
{
img: potatoskins,
name: "Galway Potato Skins",
desc: "Served with Irish bacon, cheddar and chives",
price: "$9",
},
{
img: friedpickles,
name: "Fried Pickles",
desc: "Thick-cut chips, beer battered, with house-made ranch",
price: "$8",
},
{
img: mozzarellasticks,
name: "Mozzarella Sticks",
desc: "Slightly breaded, golden fried and served with warm marinara sauce",
price: "$8",
},
],
},
{
section: "Soups & Salads",
list: [
{
img: caesarsalad,
name: "Caesar Salad",
desc: "Crisp romaine, parmesan cheese, brioche croutons, classic dressing",
price: "$14",
},
{
img: cobbsalad,
name: "Cobb Salad",
desc: "Romaine, tomato, egg, red onion, avocado, blue cheese, smoked bacon",
price: "$15",
},
{
img: housesalad,
name: "House Salad",
desc: "Mixed greens, tomato, cucumber, croutons, shredded cheese. Can add grilled or fried chicken for $3",
price: "$10",
},
{
img: greeksalad,
name: "Greek Chicken Salad",
desc: "Romaine, black olives, banana peppers, tomato, cucumber, feta, and greek feta dressing",
price: "$11",
},
{
img: potatosoup,
name: "Loaded Potato Soup",
desc: "Topped with cheese and crispy bacon and served with dipping bread",
price: "$7",
},
{
img: beefstew,
name: "Guinness Beef Stew",
desc: "Braised beef, root vegetables and potatoes simmered in a Guinness broth",
price: "$14",
},
],
},
...
MenuItems.tsx的代码:
import { useAppSelector, useAppDispatch } from "../app/hooks";
import "../styles/Order.scss";
import "../App.tsx";
const MenuItems = (props: any): JSX.Element => {
const dispatch = useAppDispatch();
// console.log(props);
const menu = useAppSelector((state) => state.menu);
return (
<div>
<div className="menu-nav">
<ul>
<li>
<a href="#Starters">Starters</a>
</li>
<li>
<a href="#Soups & Salads">Soups & Salads</a>
</li>
<li>
<a href="#Traditional Classics">Traditional Classics</a>
</li>
<li>
<a href="#Burgers & Sandwiches">Burgers & Sandwiches</a>
</li>
<li>
<a href="#Sides">Sides</a>
</li>
<li>
<a href="#Drinks">Drinks</a>
</li>
<li>
<a href="#Desserts">Desserts</a>
</li>
</ul>
</div>
<div className="item-flex">
{menu.map((item, index) => {
return (
<div key={index} className="">
<h1 id={item.section}>{item.section}</h1>
<div className="item-grid">
{item.list.map((c, i) => {
return (
<div key={i} className="item-section">
<img src={c.img} alt="food image" />
<p>{c.name}</p>
<p>{c.desc}</p>
<p>{c.price}</p>
<button
key={c.name}
onClick={() =>
dispatch({
type: "ADD_TO_CART",
payload: item,
})
}
>
Add To Cart
</button>
</div>
);
})}
</div>
</div>
);
})}
</div>
</div>
);
};
export default MenuItems;
购物车代码.tsx:
import { NavLink } from "react-router-dom";
import { useAppDispatch, useAppSelector } from "../app/hooks";
import "../styles/Order.scss";
const Cart = (): JSX.Element => {
const cart = useAppSelector((state) => state.items);
const dispatch = useAppDispatch();
return (
<div className="">
<h1>Cart</h1>
{cart.map((item, index) => {
return (
<div key={index}>
{item.list.map((c, i) => {
return (
<div key={i}>
<p>{c.name}</p>
<p>{c.price}</p>
<button
key={c.name}
onClick={() =>
dispatch({ type: "REMOVE_FROM_CART", payload: item })
}
>
Remove From Cart
</button>
</div>
);
})}
</div>
);
})}
<NavLink to="/ordercomplete">Order Complete</NavLink>
</div>
);
};
export default Cart;
rootReducer.tsx:
type Action = {
type: string;
payload?: any;
};
interface CommonFood {
img: any;
name: string;
desc: string;
price: string;
}
interface FoodDetail {
section: string;
list: Array<CommonFood>;
}
const initialMenu = [
...
};
type State = {
menu: FoodDetail[];
items: FoodDetail[];
};
const initialState: State = {
menu: initialMenu,
items: [],
};
const rootReducer = (state = initialState, action: Action) => {
switch (action.type) {
case "ADD_TO_CART":
const newItems = state.items;
console.log(newItems);
return { ...state, items: [...newItems, action?.payload] };
case "REMOVE_FROM_CART":
return {
...state,
items: [...state.items].filter((item) => item !== action.payload),
};
default:
return state;
}
};
export default rootReducer;
那么,基于我给出的代码,我如何改变根化简器中的“ADD_TO_CART”操作类型,使其不再给出数组中的所有5个项,而是指向数组中的一个项呢?或者我需要改变其他的东西吗?我知道我需要以某种方式指向它的索引来获取特定的值,但是我一直在为该尝试什么而挣扎。任何帮助都非常感谢!
1条答案
按热度按时间1cklez4t1#
您的分派会指涉功能表状态中的料号。每个料号实际上都是描述功能表区段的对象,而不是实际的购物车料号。
我知道我需要以某种方式将它的索引作为目标来获取那个特定的值,但我一直在为该尝试什么而挣扎。
正如您所描述的问题,您不需要索引,因为您只是将项目推入购物车。您只需要传递当前的食品项目
c
,如下所示:但是,如果您多次将相同的项目添加到购物车中,则可能希望增加该项目的计数,而不是将重复的项目推送到购物车中。
为此,您将需要某种类型的
id
来了解要递增的项,以及quantity
来跟踪每个项的计数。溶液
首先,您的
state.items
应该是CommonFood[]
类型,而不是FoodDetail[]
类型,这样您的购物车就代表了单个商品。然后,
CommonFood
或您决定用作购物车项目的任何项目都需要同时具有id
和quantity
属性:您还希望能够访问MenuItems.tsx中的当前购物车状态,以便将其传递给您的操作。
因此,在MenuItems.tsx中,您将拥有:
在这里,我已经用
cartItems
替换了当前代码中的state.items
,用itemToAdd
替换了当前代码中的c
,这使得后面的代码更容易阅读。然后,在你的行动中:
在此操作中,我们将检查购物车中是否存在该项目。
如果是,我们会增加该项目的数量。
如果没有,我们将添加该项目,并将数量设置为1。