我有一个用于存储首选项的reducer。它有两种动作类型。一个用于从数据库加载所有首选项,另一个用于更新单个首选项。我有一个独立的工作示例,但在我的应用程序中使用它会中断。
问题是我的偏好器缩减器只处理两种类型的动作,而我的应用程序有多个缩减器可以触发其他动作。使代码运行的解决方案是为与此reducer无关的操作添加第三种常规类型。但是,当我尝试访问操作的属性时,这会产生Property not found in 'object type'.
错误。
// @flow
const LOAD_PREFS_SUCCESS = 'LOAD_PREFS_SUCCESS';
const UPDATE_PREF = 'UPDATE_PREF';
type aType = {
+type: string
};
export type actionType = {
+type: typeof LOAD_PREFS_SUCCESS,
prefs: Array<{_id: string, value: any}>
} | {
+type: typeof UPDATE_PREF,
id: string,
value: any
};
export default (state: {} = {}, action: actionType) => {
if (action.type === LOAD_PREFS_SUCCESS) {
action.prefs.forEach(p => {
console.log(p);
});
}
switch (action.type) {
case LOAD_PREFS_SUCCESS: {
const newState = {};
action.prefs.forEach(p => {
newState[p._id] = p.value;
});
return newState;
}
case UPDATE_PREF: {
return { ...state, [action.id]: action.value };
}
default:
return state;
}
};
这是有效的流程,但是当应用程序实际运行时,当类型为INIT_APP
的某个操作运行时,我会收到错误消息。该错误显示为action must be one of:
,然后它列出了我在actionType
中的两种类型作为预期和{ type: string }
的实际值。
我可以通过向actionType
添加第三种类型来运行应用程序:
export type actionType = {
+type: typeof LOAD_PREFS_SUCCESS,
prefs: Array<{_id: string, value: any}>
} | {
+type: typeof UPDATE_PREF,
id: string,
value: any
} | {
+type: string
};
即使应用程序现在运行没有错误,它也不会传递流式检查。抛出Property not found in object type
的错误。 Here is an example on flow.org
答案 0 :(得分:0)
由于每个reducer最终都会看到每个动作,因此您需要此reducer函数的类型包含应用程序中的所有可能操作。我通常会在应用程序中定义一个变体actionType
,并在每个reducer中使用它。
您的上一个代码示例不起作用的原因是因为第三个匿名操作类型{type: string}
太模糊了。在此之前,Flow可以查看操作中的两个选项,并查看它将基于case
语句知道哪个选项。但是对于第三种操作类型,像{type: "LOAD_PREFS_SUCCESS"}
这样的操作将匹配该类型中的第三种情况。因此,测试action.type === LOAD_PREFS_SUCCESS
已经不足以证明该操作将具有prefs
密钥。
所以有两种方法可以解决这个问题:
如果您将操作类型更改为更具体并包含所有特定操作类型,则减速器应返回进行类型检查。
否则,添加一个虚拟案例,例如| {type: "NOT-REAL"}
,以便Flow强制您的reducer具有其不理解的操作的默认案例。