2017-10-05 125 views
0

通常在Redux中,我们会侦听中间件/缩减器中的操作以执行操作。然而,有时候我们对行动不感兴趣,但是商店本身也在变化。当多个操作导致相同的商店更改时,这一点尤其重要。我怎样才能以惯用的方式做到这一点?适当的模式对redux商店的更改作出反应

例如,考虑商店的部分中,我们有一个SPA的电流路径:

const store = { 
    url : '/' 
}; 

更改URL可以在3种方式之一发生:popStatepushStatereplaceState。一个合乎逻辑的实现将是对这3个进行单独的操作,以便我们可以在中间件中分别处理它们。例如: -

//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; 
} 

现在我想对网址的变化做出反应,但我不在乎如何的URL改变。我看到几个选项,但我不知道,如果其中任何正确遵循了Redux范例:

  • 使用subscribe

    这似乎气馁。从文档:

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

  • 听中间件/减速机的所有操作

    这只是正常工作在最简单的情况。如果这些行为在结构上有所不同,或者如果改变状态的整套行为未知,那么这将不起作用。

  • 减少

    您不能直接调度的减速动作后分派一个新的动作(例如STATE_CHANGED)。这意味着您需要使用超时(受竞争条件限制),或者您需要将逻辑分散到多个redux-thunk风格动作创作者身上。

  • 使用中间件派遣一个新的动作

    这就要求中间件需要注意的一切行动是如何减少。

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


元注:我知道,这个问题可以被解释为“主要根据意见”,但我不同意:我不是在寻找最好的或最优雅的解决方案,我想断言哪个解决方案符合还原范式,我相信有确切的客观答案。

+0

您尝试过任何Redux的结合?你可以签出[redux-observable](https://redux-observable.js.org)。它使用RxJS可观察模式来显示商店中的新变化。至于调度,我猜你会根据某些条件派发动作,而不管动作是如何减少的,​​ –

+0

我可能错过了某些明显的东西,但我找不到任何关于在redux中侦听存储更改的内容,观察到的。我只看到一种订阅动作的方式,但这不是我想要的。我错过了什么吗? – Tiddo

+0

您无法订阅操作。你只需发送它们。您订阅商店,然后通过调用getState方法'store.getState()'''''''''''''''''''获得订阅监听器中的新状态。 –

回答

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()); 
    };