Javascript Redux从Reducer中查看其他状态

Javascript Redux从Reducer中查看其他状态,javascript,redux,Javascript,Redux,设想一个包含两个组件的UI: 我们从服务器上拉下一组用户: [ { name: 'John', enjoys: ['Sailing', 'Running'] }, { name: 'Bob', enjoys: ['Running', 'Eating'] }, { name: 'Frank', enjoys: ['Sailing', 'Eating'] } ] UI看起来有点像这样: { ui: { fil

设想一个包含两个组件的UI:

我们从服务器上拉下一组用户:

[
  {
    name: 'John',
    enjoys: ['Sailing', 'Running']
  },
  {
    name: 'Bob',
    enjoys: ['Running', 'Eating']
  },
  {
    name: 'Frank',
    enjoys: ['Sailing', 'Eating']
  }
]
UI看起来有点像这样:

{
  ui: { 
    filter: {enjoys: 'Sailing'},
    userList: {selected: 'John'}
  }
  data: [user array]
}
过滤器:航行跑步

用户列表:

约翰

弗兰克

您可以单击过滤器或用户。为了达到这个阶段,我们点击了“帆船”,然后点击了“弗兰克”(也许我们在屏幕中间看到了一张弗兰克的好照片)。 我的Redux状态是使用组合减速机构建的,如下所示:

{
  ui: { 
    filter: {enjoys: 'Sailing'},
    userList: {selected: 'John'}
  }
  data: [user array]
}
我有两个动作,
选择用户
选择过滤器

当我点击一个过滤器(
SELECT\u filter
fires)时,如果用户仍在过滤器中,我希望
ui.userList.selected
保持不变,如果用户不在过滤器中,则
ui.userList.selected
设置为null

因此,如果我现在单击Eating,我将看到一个列表,其中有Bob和Frank,Frank被选中。但如果我点击Running,我会看到John和Bob,但都没有被选中

然而,在传统的Redux方法中,我很难做到这一点。当
userList
reducer看到
SELECT\u FILTER
操作时,它无法检查
data
状态以查看当前选定的用户是否仍处于该过滤条件

正确的方法是什么

function filter(state = {enjoys: null}, action) {
  switch (action.type) {
    case SELECT_FILTER:
      return {
        ...state,
        enjoys: action.enjoys
      }
    default:
      return state
  }
}

function userList(state = {selected: null}, action) {
  switch (action.type) {
    case SELECT_USER:
      return {
        ...state,
        selected: action.name
      }
    default:
      return state
  }
}

const ui = combineReducers({
  filter,
  userList
})

let initialUsers = [
  {
    name: 'John',
    enjoys: ['Sailing', 'Running']
  },
  {
    name: 'Bob',
    enjoys: ['Running', 'Eating']
  },
  {
    name: 'Frank',
    enjoys: ['Sailing', 'Eating']
  }
]

const rootReducer = combineReducers({
  ui,
  data: (state=initialUsers) => state // in reality, loaded from server
})

export default rootReducer

您需要对此执行另一个操作

如果要在数据缩减器中筛选用户,则在检测到用户数组已更改时,需要在组件的一个挂钩(componentWillUpdate或componentWillReceiveProps)中分派操作。此操作将为过滤器缩减器提供当前用户数组,您可以在其中根据需要设置所选字段


如果您正在筛选服务器中的用户,我想您已经有了一个操作,如FETCH_users_SUCCESS,可以用于此操作。

它应该由过滤器缩减器处理。您需要将用户数据作为操作负载的一部分发送。因此,reducer可以计算所选的用户逻辑。你应该考虑添加一个新的动作,就像@ CuttAs建议的那样。 减速器应该只知道一小部分状态

描述逻辑的好地方是动作创建者。使用redux thunk,您将能够根据全球状态做出决策

function selectFilter(enjoys) {
  return (dispatch, getState) => {
    dispatch({type: SELECT_FILTER, enjoys});
    // if getState().ui.userList.selected exists in getState().data
    dispatch({type: SELECT_USER, name: null});
  }
};

我的用户列表容器只将过滤后的用户列表传递给用户列表组件,我知道我们应该尽可能保持“哑”或简单。让一个组件在收到新道具时触发一个动作,对我来说,这似乎不是一个清晰的关注点分离?这应该在任何时候点击过滤器时计算,而不是在用户列表收到新道具时?我也不确定这里的数据流?我们发送SELECT_FILTER事件,容器将新的筛选用户列表传递给用户列表组件,然后状态中的所选用户与屏幕上显示的用户之间可能存在不匹配,组件将在组件willupdate钩子发送“FETCH\u USERS\u SUCCESS”操作并更新所选用户之前呈现?本质上,我可以看到这是如何工作的,但这真的比在整个状态树中查找并在每次触发SELECT_FILTER操作时计算所选用户的reducer好吗?如果有多个不同的筛选器组件/reducer,每个组件/reducer都具有不同的状态,该怎么办?例如,“享受过滤器”和“年龄过滤器”。那么这两个减速机中的哪一个应该拥有这个任务?我认为将“所选用户”状态保留在可能由许多不同的过滤器组件之一拥有的状态中是没有意义的?特别是如果我们想重用组件,有些页面可能有“享受过滤器”和“年龄过滤器”,有些则两者兼有。