2016-08-18 74 views
1

我正尝试在React/Redux中创建一个航班搜索应用程序,在主屏幕中显示我的所有航班结果,并在侧边栏中显示不同类型的过滤器显示复选框。 (作为例子,请参见this example在反应中更新深嵌套状态(规范化)

该滤波器由类型分组,例如出发站,到达站等在一个规范化的嵌套状态,其中每个元素具有以下性质中创建的所有filterelements离开时间:

"type": "airlines",   // this is the group type 
"checked": true,    // will be switched true or false 
"label": "Brittish Airways" // this is the display label 

当我点击我的阵营视图复选框中的一个,下面的动作将被解雇:

export function filterFlightOffers(item, index) { 
    return { 
     type: 'FILTER_FLIGHT_OFFERS', 
     grouptype, 
     id 
    } 
} 

我想我的终极版减速器更新状态(开关检查值),并返回新的状态(例如,我mmutable)。在网上查看例子,我反应了解决方案,例如用扩展运算符复制新状态,例如, ...状态并用切换的选中项目更新spefic元素,例如, {[action.id]:选中,!选中}。

但我只是不能得到它的工作,我认为由于我有一个深层嵌套状态的事实。因此,我删除了行动和减速器的复杂性,并做了一个简单的jsfiddle应该只是console.log一个新的不可变'改变'状态。

有人可以帮助我吗?

http://jsfiddle.net/gzco1yp7/4/

谢谢!

+0

为什么在'state [action.id]'里面嵌套'... state [action.id]'?如果你能解释你的行为和你想要做什么,那么帮助会更容易一些。例如,也许你正在尝试用'action.exercise'更​​新'action.id'练习。你在这里所拥有的和你在小提琴中的状态根本不符合。 – ajmajmajma

+0

O,我真的很抱歉。显示在应用程序中的代码与我的真实代码无关。它只是一个在线例子的副本,显示了principe。我正在处理的代码在小提琴中。为了使事情更容易,我已经删除了整个行动。只有寻找解决方案才能复制初始状态并更新其中的特定深层元素......我将相应地更新我的初始问题。 – user3611459

+0

不用担心,这两个例子之间没有清晰的图片显示你正在尝试做什么。如果你能清楚地描述你在状态中想要改变的是什么,以及如何(例如你将行为传递给你的减速器),我可以告诉你如何用不变的方法来实现它... – ajmajmajma

回答

1

如果你的状态看起来是这样的:

{  
    result: [1,2,3,4], 
    entities: { 
    searchitems: { 
     1: { 
     "type": "matchAirlines", 
     "checked": false, 
     "label": "Match airlines" 
     }, 
     2: { 
     "type": "airlines", 
     "checked": true, 
     "label": "Air France" 
     }, 
     3: { 
     "type": "airlines", 
     "checked": true, 
     "label": "Brittish Airways" 
     } 
    }, 
    counts: 
     1: { "count": 2001 }, 
     2: { "count": 579 }, 
     3: { "count": 554 } 
    } 
    } 
} 

...你减速看起来是这样的:

function reducer(state, action) { 

    switch (action.type) { 
    case 'FILTER_FLIGHT_OFFERS': 
     return { 
     ...state, 
     entities: { 
      ...state.entities, 
      searchItems: Object.keys(state.entities.searchItems).reduce((newItems, id) => { 
      const oldItem = state.entities.searchItems[id]; 
      if (oldItem.type === action.groupType) { 
       newItems[id] = { ...oldItem, checked: id === action.id }; 
      } else { 
       newItems[id] = oldItem; 
      } 
      return newItems; 
      }, {}) 
     } 
     }; 
    } 

    return state; 
} 

如果使用combineReducers,并创建一个减速只是这更简单你的searchItems。并且lodash也可以简化:

import mapValues from 'lodash/mapValues'; 

function searchItemsReducer(state, action) { 

    switch (action.type) { 
    case 'FILTER_FLIGHT_OFFERS': 
     return mapValues(state, (oldItem, id) => (
     oldItem.type === action.groupType 
      ? { ...oldItem, checked: id === action.id }; 
      : oldItem 
    )); 
    } 

    return state; 
} 
+0

Thnx,特别是第二条建议让我觉得......为什么不让我的状态变得更容易呢?我转换为一个简单的对象数组,现在可以使用.map和.filter来使事情发挥作用。非常感谢您的回答! – user3611459