流类型+ Redux:与其他Reducer

时间:2017-08-28 01:36:02

标签: redux flowtype

我有一个用于存储首选项的reducer。它有两种动作类型。一个用于从数据库加载所有首选项,另一个用于更新单个首选项。我有一个独立的工作示例,但在我的应用程序中使用它会中断。

问题是我的偏好器缩减器只处理两种类型的动作,而我的应用程序有多个缩减器可以触发其他动作。使代码运行的解决方案是为与此reducer无关的操作添加第三种常规类型。但是,当我尝试访问操作的属性时,这会产生Property not found in 'object type'.错误。

Working flow example

// @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

1 个答案:

答案 0 :(得分:0)

由于每个reducer最终都会看到每个动作,因此您需要此reducer函数的类型包含应用程序中的所有可能操作。我通常会在应用程序中定义一个变体actionType,并在每个reducer中使用它。

您的上一个代码示例不起作用的原因是因为第三个匿名操作类型{type: string}太模糊了。在此之前,Flow可以查看操作中的两个选项,并查看它将基于case语句知道哪个选项。但是对于第三种操作类型,像{type: "LOAD_PREFS_SUCCESS"}这样的操作将匹配该类型中的第三种情况。因此,测试action.type === LOAD_PREFS_SUCCESS已经不足以证明该操作将具有prefs密钥。

所以有两种方法可以解决这个问题:

  1. 如果您将操作类型更改为更具体并包含所有特定操作类型,则减速器应返回进行类型检查。

  2. 否则,添加一个虚拟案例,例如| {type: "NOT-REAL"},以便Flow强制您的reducer具有其不理解的操作的默认案例。