问题描述
我有一个简单的 Grocery Shopping 应用程序,我想在其中使用 Set()
,但是当我尝试使用 Set()
时出现各种错误。我正在使用带有 TypeScript 的 MobX。
types.ts
export type Item = {
name: string;
instock: number;
price: number;
};
export type Buyer = {
cash: number;
items: Array<Pick<Item,'name'> & { quantity: number }>;
};
export type IStore = {
items: Item[];
buyer: Buyer;
};
store.ts
import { observable,action,set,computed,makeObservable } from 'mobx';
import type { Item,IStore,Buyer } from './types';
export class Store implements IStore {
items: Item[] = [
{
name: "Egg",instock: 30,price: 4
},{
name: "Apple",instock: 24,price: 20
},{
name: "Banana",instock: 60,price: 8
}
]
buyer: Buyer = {
cash: 50,items: [],}
constructor() {
makeObservable(this,{
items: observable,buyer: observable,buyItem: action.bound,});
}
buyItem(name: string,price: number,quantity: number) {
if (this.buyer.cash - price * quantity > 0) {
this.buyer.items.push({ name,quantity })
this.buyer.cash = this.buyer.cash - price * quantity
}
}
}
export const store = new Store();
我想让 buyer
变成 Set()
。例如,types.ts 应该将 buyer
变成:
.
.
.
export type IStore = {
.
.
.
buyer: new Set<Buyer>();
};
同样,我应该能够更改 store.ts
。 The docs 没有完整的例子。我该怎么做?
Stackblitz 复制 → https://stackblitz.com/edit/react-mobx-set-not-working?file=store.ts
解决方法
我使用了 Map
而不是 Set
,但是如果您想用 Map
替换 Set
,它也可以完美运行。
我使用带有 Map
的 .has()
来检查存储的项目 name
是否唯一,因此它的作用类似于 Set
。
可以找到 Stackblitz → https://stackblitz.com/edit/react-mobx-grocery-shopping?file=index.tsx
types.ts
export type Item = {
name: string;
instock: number;
price: number;
};
export type BuyerItem = Pick<Item,'name'> & { quantity: number };
export type Buyer = {
cash: number;
items: Map<string,number>;
};
export type IStore = {
items: Item[];
buyer: Buyer;
};
store.ts
import { observable,action,makeObservable } from 'mobx';
import type { Item,IStore,BuyerItem,Buyer } from './types';
export class Store implements IStore {
items: Item[] = [
{
name: "Egg",instock: 30,price: 4
},{
name: "Apple",instock: 24,price: 20
},{
name: "Banana",instock: 60,price: 8
}
]
buyer: Buyer = {
cash: 120,items: new Map<string,number>(),}
constructor() {
makeObservable(this,{
items: observable,buyer: observable,buyItem: action.bound,});
}
buyItem(name: string,price: number,quantity: number) {
if (this.buyer.cash - price * quantity >= 0) {
if (this.buyer.items.has(name)) {
const alreadyBought = this.buyer.items.get(name)
this.buyer.items.set(name,quantity + alreadyBought)
}
else
this.buyer.items.set(name,quantity)
this.buyer.cash = this.buyer.cash - price * quantity
}
}
}
export const store = new Store();
index.tsx
import React,{ Component } from 'react';
import { render } from 'react-dom';
import { observer } from "mobx-react";
import { useStore } from "./context";
const App = observer(() => {
const { items,buyer,buyItem } = useStore()
const buyerItems = Array.from(buyer.items)
return (
<div>
<h1>Grocery Shopping</h1>
<table style={{ width: 400,lineHeight: 2,border: "1px solid black",textAlign: "center" }}>
<thead>
<tr>
<th>Item</th>
<th>Price</th>
<th>In Stock</th>
<th>Purchase</th>
</tr>
</thead>
<tbody>
{items.map(item => (
<tr key={item.name}>
<td>{item.name}</td>
<td>${item.price}</td>
<td>{item.instock}</td>
<td>
<button onClick={() => {
buyItem(item.name,item.price,1)
}}>
Buy 1
</button>
</td>
</tr>
))}
</tbody>
</table>
<h2>${buyer.cash} balance left</h2>
{buyerItems.length > 0 && (
<>
<h2>Customer Bought:</h2>
<ul>
{buyerItems.map(item => {
return <li key={item[0]}>{item[1]} {item[0]}</li>
})}
</ul>
</>
)}
</div>
)
})
render(<App />,document.getElementById('root'));