适当的模式对redux存储变化做出反应

时间:2017-10-05 08:28:01

标签: javascript redux

通常在Redux中,我们会监听中间件/ reducer中的操作以执行操作。但是,有时我们对行动不感兴趣,但在商店中自行更改。当多个操作可能导致相同的商店更改时,这尤其重要。我怎么能以惯用的方式这样做?

例如,考虑我们拥有SPA当前路径的商店的一部分:

const store = {
    url : '/'
};

更改网址可以通过以下三种方式之一进行:popStatepushStatereplaceState。逻辑实现是为3分别执行操作,以便我们可以在中间件中单独处理它们。 E.g:

//actions
function popState(url) {
  return { type : 'POP_STATE', url };
}
function pushState(url) { 
  return { type : 'PUSH_STATE', url };
}
function replaceState(url) {
  return { type : 'REPLACE_STATE', url };
}

// middleware
store => next => action => {
  switch(action.type) {
    case 'PUSH_STATE' : 
      history.pushState(null, null, action.url);
      break;
    case 'REPLACE_STATE' :
      history.replaceState(null, null, action.url);
      break;
  }
  return next(action);
}

// reducer
function (state, action) {
  switch(action.type) {
    case 'PUSH_STATE':
    case 'REPLACE_STATE':
    case 'POP_STATE':
      state.url = action.url; // (ignoring immutability to keep the example simple)
      break;
  }
  return state;
}

现在我想回复网址更改,但我不在乎 网址的更改方式。我看到了一些选项,但我不确定其中任何一个是否正确遵循redux范例:

  • 使用subscribe

    这似乎是气馁的。来自文档:

      

    这是一个低级API。最有可能的是,您不会直接使用它,而是使用React(或其他)绑定。

  • 收听中间件/ reducer中的所有操作

    这只适用于最简单的情况。如果行动的结构不同,或者如果不知道改变状态的全套行动,那么这将不起作用。

  • 在缩小

    后发送新动作(例如STATE_CHANGED

    您无法直接在reducer中调度操作。这意味着您需要使用超时(受竞争条件限制),或者需要在多个redux-thunk样式动作创建者之间展开逻辑。

  • 使用中间件发送新动作

    这要求中间件了解所有操作的减少方式。

这些解决方案中的任何一种都属于redux范式吗?我错过了吗?

Meta说明:我知道这个问题可能会被解释为主要是基于意见的问题,但我不同意:我不是在寻找最好或最优雅的解决方案,I& I" #39;我试图断言哪些解决方案符合redux范式,我相信对此有明确,客观的答案。

2 个答案:

答案 0 :(得分:1)

如果需要,使用store.subscribe() 是有效选项。如果您需要在连接的React组件之外执行此操作,则many existing libraries to help watch for changes in the store state。鉴于您正在进行与路由相关的行为,您也可能对some of the existing Redux-based routing libraries感兴趣。

答案 1 :(得分:0)

良好的模式中间件:

const logMiddleware => ({ getState, dispatch }) => next => action => {
     console.log("Before reducers have run");
     console.log(getState());
     next(action);
     console.log("After the reducers have run");
     console.log(getState());
     };