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

React + Redux, where should my UI-related calculations go, container components, or reducers?

我正在从事一个中型到大型 react/redux 项目,我正在努力寻找 react/redux 的最佳实践。

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

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

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

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

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

我认为这两个选项都有意义:

如果我选择reducers,那么另一个问题来了。我应该将计算后的数据保存在商店中吗?或者只是保存源数据,并在每次渲染组件时计算它? The old React doc 说你不应该在状态中保存计算数据,不确定是否适用于 redux。

通常:

  1. store 应该包括最小可能的状态。

  2. 派生的数据是通过reselect在mapStateToProps中计算出来的, 记住结果。将立即调用计算;

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

我认为您应该持久化集合而不是数组,因为通过键获取数据要简单得多。 如果您不打算编辑特定项目的值,您可以在 reducer 中预先计算它们。

例如通过选择器计算:

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

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

顺便说一句,集合中的顺序无法保证,因此除了集合之外,您可能还应该从服务器接收键数组。然后代码会有点不同...