React + Redux,我的UI相关计算应该放在哪里,容器组件还是Reducer?

时间:2016-12-13 09:15:39

标签: javascript reactjs redux react-redux

我正在开展一个大中型的反应/减少项目,我正在努力寻找反应/减少的最佳实践。

例如,如果我有一个饼图组件,它将采用一个简单的数组作为道具:

[{
  label: 'a',
  value: 10
}, {
  label: 'b',
  value: 6
}, ...]

但我从API服务器获取的源数据可能是这样的:

{
  a: {
    value1: 15,
    value2: 3,
    value3: 7,
    ...
  },
  b: { ... }
}

现在我必须做一些计算才能得到结果数据(比如value1 -value2 + value3 ......也许是一些过滤器...),问题是,我应该把这个计算放在 reducer (我觉得它更像是一个 getter ,它将通过connect作为道具传递到组件,如getCartProducts in this example),或者容器组件(在这种情况下可能是 Dashboard )?

我认为这两种选择都有道理:

    减速器中的
  • :我们可以保持组件清洁,并将所有逻辑放在同一个地方。

  • 容器中的
  • :因为它与UI相关,并且如果计算的数据不可重复使用(仅针对该饼图),我们可以将这种计算保留在相关组件中。

如果我选择减速机,则会出现另一个问题。我应该在商店中保存计算数据吗?或者只保存源数据,并在每次渲染组件时计算它? The old React doc表示你不应该在状态中保存计算数据,不确定redux是否为真。

1 个答案:

答案 0 :(得分:5)

<强>一般

  1. 商店应包含尽可能少的状态。

  2. 通过reselect在mapStateToProps中计算得到的数据, 记住结果。计算将立即被调用;

  3. <强>可是: 如果派生数据的形状与应用程序中使用的形状不同(或者您需要一些计算),那么 你可以在获取后立即计算。 (例如,它可能是规范化数据)

    我认为你应该坚持收集而不是数组,因为通过密钥获取数据要简单得多。 如果您不打算编辑特定项目的值,可以在减速器中预先计算它们。

    例如通过选择器计算:

    使用了选择器组合,以避免在更新过滤器时重新计算:

    import map from 'lodash/map';
    import { createSelector } from 'reselect';
    
    const getFilterKeys=(state)=>state.filter; //['a','b','c']
    //(btw it's just example... filter may be in props);
    
    const getItems=(state)=>state.entities.items;
    
    
    const calculateValues = (item) => item.value1 - item.value2 + item.value3;
    
    export const getItemsForChart = createSelector(
      [getItems],
      (items)=> map(items,(item,key)=>({label:key, value:calculateValues(item)}))
    );
    
    export const getItemsForChartWithFilter = createSelector(
      [getItemsForChart, getFilterKeys],
      (items, filterKeys)=> items.filter(item=>filterKeys.some(key=>key==item.label))
    );
    

    const mapStateToProps=(state)=>{
      return {
        chartData:getItemsForChartWithFilter(state)
      };
    };
    

    btw收集中的订单无法保证,因此除了收集之外,您可能应该从服务器数组键中接收。然后代码会有点不同......