2017-08-28 26 views
0

我有一个用于存储偏好的减速器。它有两种动作类型。一个用于加载数据库的所有首选项,另一个用于更新单个首选项。我有一个独立工作的例子,但是一旦在我的应用程序中使用它就会中断。Flow Type + Redux:不会与其他减速器的动作冲突的动作类型

问题是我的首选项reducer只能处理两种类型的操作,而我的应用程序有多个可以触发其他操作的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 typeHere is an example on flow.org

回答

0

由于每个reducer都会看到每个动作,所以您需要这种reducer功能的类型将所有可能的动作包含在您的应用中。我通常在应用程序中定义一个变体actionType,并在每个缩减器中使用该变体。

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

因此,有两种方法来解决这个问题:

  1. 如果你改变你的动作类型更加具体的,包括所有具体的动作类型,你的减速应该回去类型检查。

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

+0

感谢亚当,所以我需要为每一个动作创建actionTypes,并可能将其存储在它自己的文件或我的根reducer文件中。这听起来非常麻烦,特别是当我考虑一些我使用的库时,它还钩入了像react-router和react-redux-form这样的redux状态。有没有一种很好的解决方法,或者我可以选择输入所有内容或停止使用流? – yourfavorite

+0

那么,它将很难给这个reducer的action参数一个类型,而没有办法引用这个action的类型。你可以用'type:'A'|替换'type:string' 'B'| ......“也列出其他类型。然后,当您添加使用每种动作类型的逻辑时,将其分解并声明动作将具有的数据类型。 – Adam

+1

看起来你也参与了github,并在那里用一个可行的解决方案回答了我的问题:D想要在这里抛出它,所以我可以给你答案的信誉,并希望能帮助其他人在未来遇到这个问题?谢谢! – yourfavorite

相关问题