redux - Flow中的“强制展开”?
问题描述
我的减速器中有这个辅助函数,它具有给定的状态:
type CustomerCollection = { [number]: Customer }
type CustomerState = {
+customers: ?CustomerCollection,
+newItem: ?(Customer | Review),
+searchResults: ?(Customer[]),
+error: ?string,
+isLoading: boolean
};
function customerWithReview(review: Review): Customer {
const id: number = review.customerId;
const oldCustomer: Customer = state.customers[id];
const newReviews: Review[] = [review, ...oldCustomer.reviews];
return Object.assign(oldCustomer, { reviews: newReviews });
}
id
我在const oldCustomer: Customer = state.customers[id];
说的时候得到一个流错误Cannot get state.customers[id] because an index signature declaring the expected key/value type is missing in null or undefined
。
这是因为?CustomerCollection
.state.customers
我可以通过确保customers
不为空来消除错误:
if (state.customers) {
const oldCustomer: Customer = state.customers[id];
const newReviews: Review[] = [review, ...oldCustomer.reviews];
return Object.assign(oldCustomer, { reviews: newReviews });
}
但随后问题就上链了,因为我没有任何东西可以从函数返回。
我当然可以将其扩展为:
function customerWithReview(review: Review): Customer {
if (!state.customers) {
return new Customer();
} else {
const id: number = review.customerId;
const oldCustomer: Customer = state.customers[id];
const newReviews: Review[] = [review, ...oldCustomer.reviews];
return Object.assign(oldCustomer, { reviews: newReviews });
}
}
但在实际实践中,将我们带到 reducer 的这个分支的操作永远不会被调用 if state.customers
is null
,而且我们永远不会返回new Customer()
,如果我们这样做了,它也没有任何用处。state.customers
可以为空,以便区分“我们还没有获取客户 ( state.customers == null
)”和“我们已经获取了客户但没有客户 ( state.customers == {}
)。
如果我可以断言state.customers
在这些情况下始终存在,那会容易得多,在 Swift 中我会使用强制展开:
const oldCustomer: Customer = state.customers![id];
我可以用 Flow 做这样的事情吗?
或者,考虑到只有我的GET_CUSTOMERS_FAILURE
行动才能处理state.customers == null
,有没有其他方法可以重组我的减速器,这样会更容易一些?一个完全独立fetchReducer
的具有可为空的客户集合,而其余操作属于不同的减速器?
解决方案
您可以使用invariant
功能(检查它是否在这里工作):
type Customer = { id: number, reviews: Array<Review> };
type Review = { customerId: number };
type CustomerCollection = { [number]: Customer }
type CustomerState = {
+customers: ?CustomerCollection,
+newItem: ?(Customer | Review),
+searchResults: ?(Customer[]),
+error: ?string,
+isLoading: boolean
};
declare var state: CustomerState;
declare function invariant(): void;
function customerWithReview(review: Review): Customer {
const id: number = review.customerId;
invariant(state.customers, 'No customers and I don\'t know why');
const oldCustomer: Customer = state.customers[id];
const newReviews: Review[] = [review, ...oldCustomer.reviews];
return Object.assign(oldCustomer, { reviews: newReviews });
}
您可以在项目中的某个地方实现它并在必要时导入。
你可以像这样实现它:
export function invariant<T>(value: ?T, falsyErrorMessage: string, errorParams?: Object): void {
if (!value) {
log.error(falsyErrorMessage, errorParams || {});
throw new Error(INVARIANT_ERROR_MESSAGE);
}
}
不幸的是,函数的名称在流程中是硬编码的。
替代变体只是在您的函数中添加一个if
并直接引发错误。customerWithReview
推荐阅读
- c# - WPF InputSimulator 不适用于用户控件
- java-8 - Java 8 - SQL 时间戳到即时格式正确的时间
- api - 没有“假期回复”的Gmail中的自动回复?
- git - 如何列出git未跟踪的文件并根据修改时间对其进行排序?
- python-3.x - 如何通过事件与 matplotlib 中的条进行交互
- python - “if”语句不移动到“else”子句
- c# - “AddReward”不添加奖励:Unity mlagents
- powershell - 无法将 xlsx 中的数据提取到 powershell
- go - 混合打印和 fmt.Println 和堆栈增长
- javascript - 是否可以从 Javascript 中的 require() 文件中“向后引用”某些内容?