【问题标题】:Flow Type + Redux: Type for action that won't conflict with actions for other reducersFlow Type + Redux:不会与其他 reducer 的操作冲突的操作类型
【发布时间】:2017-08-30 03:13:29
【问题描述】:

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

问题是我的偏好减速器只处理两种类型的动作,而我的应用程序有多个触发其他动作的减速器。让代码运行的一种解决方案是为与此 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

【问题讨论】:

    标签: redux flowtype


    【解决方案1】:

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

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

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

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

    2. 否则,请添加一个虚拟案例,例如 | {type: "NOT-REAL"},以便 Flow 强制您的减速器为其不理解的操作设置默认案例。

    【讨论】:

    • 感谢 Adam,所以我需要为每个操作创建 actionTypes,并可能将其存储在自己的文件或我的根减速器文件中。这听起来非常麻烦,尤其是当我考虑到我使用的一些库也像 react-router 和 react-redux-form 一样挂钩到 redux 状态时。有没有解决这个问题的好方法,或者我可以选择输入所有内容或停止使用流程?
    • 好吧,如果没有办法引用动作的类型,就很难给这个减速器的动作参数指定一个类型。您可以将type: string 替换为type: 'A' | 'B' | ...,也可以列出其他类型。然后,当您添加使用每种操作类型的逻辑时,将其分解并声明该操作将具有的数据类型。
    • 看起来你也参与了 github 并在那里用一个可行的解决方案回答了我的问题:D 想把它扔在这里,这样我就可以给你答案,希望能帮助其他运行的人将来进入这个?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 2015-10-21
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多