Mobx 状态树引用类型和 Typescript
Mobx State Tree reference type and Typescript
我在 React 应用程序中使用带有 Typescript 的 mobx-state-tree。而且,我遇到了 Typescript 的问题,它抱怨 mobx 类型 types.safeReference
的类型。看起来模型定义中 safeReference
的类型与您使用 .create()
实际创建模型实例时的类型不同。在我的代码中,selectedProduct
的类型在 productStore
中转换为 string | number | undefined | null
,但在模型定义中是 IStateTreeNode<...> | undefined | null
,这就是我在根存储中出错的原因。我该如何解决?
这是我的产品商店:
import { types } from "mobx-state-tree";
const Product = types.model("Product", {
id: types.identifier,
name: types.string
})
const ProductStore = types
.model("ProductStore", {
products: types.array(Product),
selectedProduct: types.safeReference(Product),
})
.actions((self) => ({
// actions here
}));
export const productStore = ProductStore.create({
products: [],
selectedProduct: undefined // the type here is different from the type in the actual model
});
而且,这是我的根存储区:
import { types } from "mobx-state-tree";
import ProductStore, { productStore } from "./product-store";
const RootStore = types.model('RootStore', {
productStore: ProductStore
})
export const rootStore = RootStore.create({
productStore: productStore // Here is where I get the typescript error.
});
更新:
重现此问题的另一种方法是尝试创建自定义引用。 getter 会抱怨 undefined
无法分配给类型 {...}。
const ProductByIdReference = types.maybeNull(
types.reference(Product, {
get(id: number, parent: Instance<typeof ProductStore>) {
return parent.products.find(p => p.id === id) || undefined
},
set(value: Instance<typeof Product>) {
return value.id
}
})
)
我详细检查了你的问题并写了一个解决方案,这是如何正确使用 mst
rootStore
概念,不需要创建你的商店或对象的实例,只是 @inject
它直接在组件内部:
// Product Store
import { types, Instance } from "mobx-state-tree";
const Product = types.model("Product", {
id: types.identifier,
name: types.string
})
const Store = types
.model("ProductStore", {
products: types.array(Product),
selectedProduct: types.safeReference(Product),
})
.actions((self) => ({
// actions here
}));
type ProductStoreType = typeof Store;
interface ProductStoreTypeInterface extends ProductStoreType {}
export interface ProductStoreInterface extends Instance<ProductStoreTypeInterface> {}
export const ProductStore: ProductStoreTypeInterface = Store;
// Root Store
import { types } from "mobx-state-tree";
import { ProductStore } from "./product-store";
const RootStore = types.model('RootStore', {
productStore: types.late(() => types.optional(ProductStore, {})),
})
// And now you can create rootStore with empty object
export const rootStore = RootStore.create({});
// Component
import { inject, observer } from 'mobx-react';
import { SettingStoreInterface } from "../settings/SettingStore";
import React from "react";
interface ComponentProps {}
interface InjectedProps extends ComponentProps {
productStore: ProductStoreInterface;
}
@inject('productStore')
@observer
class SomeComponent extends React.Component<ComponentProps> {
componentDidMount() {
const { productStore } = this.props as InjectedProps;
console.log(productStore.products);
}
}
一般来说,当您尝试在通常使用实例的地方使用快照时,您会使用 cast
. When you are trying to use an instance where a snapshot is typically used, you use castToSnapshot
。
export const rootStore = RootStore.create({
productStore: castToSnapshot(productStore)
});
我在 React 应用程序中使用带有 Typescript 的 mobx-state-tree。而且,我遇到了 Typescript 的问题,它抱怨 mobx 类型 types.safeReference
的类型。看起来模型定义中 safeReference
的类型与您使用 .create()
实际创建模型实例时的类型不同。在我的代码中,selectedProduct
的类型在 productStore
中转换为 string | number | undefined | null
,但在模型定义中是 IStateTreeNode<...> | undefined | null
,这就是我在根存储中出错的原因。我该如何解决?
这是我的产品商店:
import { types } from "mobx-state-tree";
const Product = types.model("Product", {
id: types.identifier,
name: types.string
})
const ProductStore = types
.model("ProductStore", {
products: types.array(Product),
selectedProduct: types.safeReference(Product),
})
.actions((self) => ({
// actions here
}));
export const productStore = ProductStore.create({
products: [],
selectedProduct: undefined // the type here is different from the type in the actual model
});
而且,这是我的根存储区:
import { types } from "mobx-state-tree";
import ProductStore, { productStore } from "./product-store";
const RootStore = types.model('RootStore', {
productStore: ProductStore
})
export const rootStore = RootStore.create({
productStore: productStore // Here is where I get the typescript error.
});
更新:
重现此问题的另一种方法是尝试创建自定义引用。 getter 会抱怨 undefined
无法分配给类型 {...}。
const ProductByIdReference = types.maybeNull(
types.reference(Product, {
get(id: number, parent: Instance<typeof ProductStore>) {
return parent.products.find(p => p.id === id) || undefined
},
set(value: Instance<typeof Product>) {
return value.id
}
})
)
我详细检查了你的问题并写了一个解决方案,这是如何正确使用 mst
rootStore
概念,不需要创建你的商店或对象的实例,只是 @inject
它直接在组件内部:
// Product Store
import { types, Instance } from "mobx-state-tree";
const Product = types.model("Product", {
id: types.identifier,
name: types.string
})
const Store = types
.model("ProductStore", {
products: types.array(Product),
selectedProduct: types.safeReference(Product),
})
.actions((self) => ({
// actions here
}));
type ProductStoreType = typeof Store;
interface ProductStoreTypeInterface extends ProductStoreType {}
export interface ProductStoreInterface extends Instance<ProductStoreTypeInterface> {}
export const ProductStore: ProductStoreTypeInterface = Store;
// Root Store
import { types } from "mobx-state-tree";
import { ProductStore } from "./product-store";
const RootStore = types.model('RootStore', {
productStore: types.late(() => types.optional(ProductStore, {})),
})
// And now you can create rootStore with empty object
export const rootStore = RootStore.create({});
// Component
import { inject, observer } from 'mobx-react';
import { SettingStoreInterface } from "../settings/SettingStore";
import React from "react";
interface ComponentProps {}
interface InjectedProps extends ComponentProps {
productStore: ProductStoreInterface;
}
@inject('productStore')
@observer
class SomeComponent extends React.Component<ComponentProps> {
componentDidMount() {
const { productStore } = this.props as InjectedProps;
console.log(productStore.products);
}
}
一般来说,当您尝试在通常使用实例的地方使用快照时,您会使用 cast
. When you are trying to use an instance where a snapshot is typically used, you use castToSnapshot
。
export const rootStore = RootStore.create({
productStore: castToSnapshot(productStore)
});