首页 文章

流类型Redux:不会与其他Reducer的操作冲突的操作类型

提问于
浏览
0

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

问题是我的首选项reducer只处理两种类型的操作,而我的app有多个reducers来触发其他操作 . 使代码运行的解决方案是为与此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

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

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

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

    • 如果将操作类型更改为更具体并包含所有特定操作类型,则reducer应返回到类型检查 .

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

相关问题