Javascript Redux:在reducer函数中调用store.getState(),这是反模式吗?

Javascript Redux:在reducer函数中调用store.getState(),这是反模式吗?,javascript,redux,Javascript,Redux,我想知道,有时我有一个减速器需要另一个减速器的信息。例如,我有一个减速器: import * as ActionTypes from '../actions/action_type_constants'; import KeyCode from 'keycode.js/index'; import {store} from "../index"; import {mod} from "../pure_functions"; export function selectedCompletion(

我想知道,有时我有一个减速器需要另一个减速器的信息。例如,我有一个减速器:

import * as ActionTypes from '../actions/action_type_constants';
import KeyCode from 'keycode.js/index';
import {store} from "../index";
import {mod} from "../pure_functions";

export function selectedCompletion(state = 0, action) {
  if (action.type === ActionTypes.arrowKeyPressed) {
    const completionsLength = store.getState().completions.data.length;
    if (action.keyCode === KeyCode.UP) {
      return mod(state - 1, completionsLength);
    } else if (action.keyCode === KeyCode.DOWN) {
      return mod(state + 1, completionsLength);
    }
  }
  return state;
}
我确实在函数的第二行调用store.getState,因为否则我无法正确确定索引

我可能会重构这个和另一个减速机,使它成为一个大减速机,但为了可读性,我更喜欢这个选项

如果在reducer中使用这种调用store.getState()的模式,我不确定是否会遇到问题。

是的,这绝对是一种反模式。减速器功能应为“纯”,且仅基于其直接输入(当前状态和动作)

Redux常见问题解答在中讨论了此类问题。基本上,您应该编写一些自定义的reducer逻辑来传递所需的附加信息,或者将更多信息放入您的操作中


我还为Redux文档编写了一个名为的部分,讨论了与reducer逻辑相关的一些重要概念。我鼓励您通读一遍。

您想要的模式是一种组合的情况,因为您正在准备基于其他域(在还原域的意义上)的其他现有状态的新状态。在Redux文档中,标题为的主题下提供了一个示例


但是,请注意,它们的示例组合了容器中的状态,而不是还原器中的状态;然而,给需要它的组件喂食

对于来到本页想知道如何将其大型应用程序升级到redux 4.0而不改进其完整的状态管理的人,因为getState等在Reducer中被禁用:

虽然我和作者一样,不赞成这种反模式,但当你意识到他们在没有任何技术原因和选择退出的情况下禁止使用这些函数时,会让人们没有更新,不幸的是他们的代码库广泛使用这种反模式。。。嗯,我提出了一个合并请求,添加了一个有重兵把守的选择退出,但它只是立即关闭了

因此,我创建了一个redux分支,它允许在创建存储时禁用禁令:

对于其他人,请使用此处的一个示例或我在中提供的方式:

另一种方法是,如果您使用react-redux,并且只在一个地方需要该操作,或者可以创建一个HOC(更高阶组件,不需要真正理解重要的是这可能会使html膨胀),则访问权限将与传递给该操作的其他参数一起使用:

const-mapState=({accountDetails:{stateOfResidenceId}})=>stateOfResidenceId;
常量映射分派=(分派)=>({
pureUpdateProduct:(stateOfResidenceId)=>dispatch({type:types.UPDATE_PRODUCT,payload:stateOfResidenceId})
});
const mergeProps=(stateOfResidenceId,{pureUpdateProduct})=>({hydratedUpdateProduct:()=>pureUpdateProduct(stateOfResidenceId)});
const addHydratedUpdateProduct=connect(mapState、mapDispatch、mergeProps)
导出默认的AddHydreatedUpdateProduct(组件);
导出常量OtherHydreatedComponent=AddHydreatedUpdateProduct(OtherComponent)
使用mergeProps时,返回的内容将添加到props中,mapState和mapDispatch仅用于提供mergeProps的参数。因此,换句话说,此函数会将其添加到组件道具(typescript语法):

(请注意,函数实际上返回操作本身,而不是void,但在大多数情况下,您将忽略这一点)

但你能做的是:

constmapstate=({accountDetails})=>accountDetails;
常量映射分派=(分派)=>({
pureUpdateProduct:(stateOfResidenceId)=>dispatch({type:types.UPDATE_PRODUCT,payload:stateOfResidenceId})
其他操作:(参数)=>调度(其他操作(参数))
});
const mergeProps=({stateOfResidenceId,…passAlong},{pureUpdateProduct,…otherActions})=>({
…很长时间,
……其他行动,
水合更新产品:()=>pureUpdateProduct(stateOfResidenceId),
});
const reduxPropsIncludingHydreatedAction=connect(映射状态、映射分派、合并Props)
导出默认ReduxPropsInIncludingHydreatedAction(ReactComponent);
这将为道具提供以下内容:

{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}
总的来说,尽管redux维护人员对扩展其软件包的功能进行了彻底的解约,以一种良好的方式将这些愿望包括在内,这将在不支持生态系统碎片化的情况下为这些功能创建一种模式,但令人印象深刻


像Vuex这样不那么顽固的软件包不会因为人们滥用反模式而产生太多问题,因为它们会丢失,同时支持一种更干净的语法,比您使用redux和最好的支持软件包归档时所需的模板更少。尽管软件包更加通用,但dochumantation更容易理解,因为它们不会像Redux文档那样迷失在细节中。

我有点困惑,getState调用如何违反基于当前状态的行为?特别是考虑到无法重新排列的第三方缩减器的使用情况。首先,“纯函数”的定义是“只依赖于其输入的函数,不修改或影响自身之外的任何东西”。引用导入的存储意味着它不是纯的。其次,这将reducer与特定的存储实例相耦合,这意味着它在测试或多个存储之类的情况下无法工作。因此,代码在大多数情况下都可以工作,但它肯定不是“正确的”。请重新阅读该FAQ条目,并获取有关如何处理问题的信息。这两个链接都会导致“找不到页面”。是的,不幸的是,我们用于构建文档的Gitbook工具最近的升级更改了URL,重定向还不能正常工作。我会更新链接
{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}