javascript - 基于道具类型渲染组件
问题描述
我有一个小型餐厅应用程序,可让用户从菜单中点餐。菜单分为三种:食物、饮料、甜点。从上到下的组件结构是 Order -> Menu -> MenuItem。我想根据类型分隔菜单页面(例如:所有食物都在名为 FOOD 的标题下,依此类推)。现在,Menu 组件从 Order 接收菜单数组作为道具,并为数组中的每个项目呈现 MenuItem。每个项目都有一个称为类型的属性。为简洁起见,我省略了与此问题无关的代码的某些部分。
//命令
export default function Order() {
const [menu, setMenu] = useState<Array<{}>>([]);
const [total, setTotal] = useState(0);
useEffect(() => {
apiFetch("menu").then((json) => setMenu(json.menu));
}, []);
async function handleSubmit(e: any) {
e.preventDefault();
const selectedItems = getSelectedItems(TotalStore);
apiFetch("order", "post", { selectedItems })
.then((json) => {
alert("Order has been submitted");
setTotal(0);
TotalStore.reset();
localStorage.setItem("last_order_id", json.order.id);
function checkOrderStatus() {
apiFetch(
`order/${json.order.id || localStorage.getItem("last_order_id")}`
).then((placedOrder) => {
const { order } = placedOrder;
if (order[0].status === 2) {
alert("Your order is ready!");
} else {
setTimeout(checkOrderStatus, 5000);
}
});
}
checkOrderStatus();
})
.catch((error) => {
alert("Server error");
});
}
function orderPlaced(total: number) {
return total !== 0 ? true : false;
}
return (
<div>
{menu.length > 0 ? (
<>
<div className="menu">
<div className="menu-title">Food Menu</div>
<form id="menu-form" onSubmit={handleSubmit} autoComplete="off">
<Menu onChange={itemChanged} props={menu} />
<button type="submit" disabled={!orderPlaced(total)}>
Place Order
</button>
</form>
</div>
<div className="order-total">
<h2>
Total: $<span>{total.toFixed(2)}</span>
</h2>
</div>
</>
) : (
<>Loading Menu</>
)}
</div>
);
}
//菜单
export default function Menu({ onChange, props }: MenuProps) {
return (
<div>
{props.map((food: any, index: number) => {
return (
<MenuItem
key={index}
onChange={onChange}
type={food.type}
item={food}
/>
);
})}
</div>
);
}
//菜单项
export default function MenuItem({ onChange, item, type }: MenuItemProps) {
return (
<div>
<article className="menu-item" data-item-type={type}>
<h3 className="item-name">{item.name}</h3>
<input
type="number"
className="menu-item-count"
min="0"
value={data.count}
onChange={menuItemCountChange}
/>
<strong className="item-price">${item.price.toFixed(2)}</strong>
</article>
</div>
);
}
解决方案
您想按food.type
属性对菜单数据进行分组。一种方法是将菜单项分类到它们的“食物类型”类别中,然后分别呈现每个组。
export default function Menu({ onChange, items }) {
const foodCategories = items.reduce((categories, item) => {
if (!categories[item.type]) {
categories[item.type] = []; // <-- new array for category type
}
categories[item.type].push(item); // <-- push item into category type
return categories;
}, {});
return (
<div>
{Object.entries(foodCategories).map(([type, foodItems]) => (
<div key={type}>
<h1>{type}</h1> // <-- category header
{foodItems.map((food, index) => ( // <-- map food items
<MenuItem
key={index}
onChange={onChange}
type={food.type}
item={food}
/>
))}
<div>
))}
</div>
);
}
推荐阅读
- android - 协程组合作业未完成
- docker - 如何从容器中检测主机操作系统?
- c++ - 什么事情会导致 GDB 在点击 main 之前出错?
- python - julia.core.JuliaError:调用 julia 代码时发生异常“ArgumentError”:使用 PyCall
- c++ - 这棵树失去了它的孩子,它只记得最新的。霍夫曼
- vim - VIM 中的颜色高亮函数调用
- c++ - 是否需要将函数声明放在头文件中并将它们的定义放在源文件中?
- java - 致命异常:java.lang.RuntimeException 无法获取应用程序信息
- java - 您可以将 Minecraft 版本的文件夹从 PC 复制并粘贴到 Mac 上吗?
- javascript - 分组条形图上的 D3js 标签