React + Redux,与UI相关的计算应该放在哪里,容器组件或化简器?

Cod*_*Cat 3 javascript reactjs redux react-redux

我正在研究中型的React / Redux项目,并且正在尝试找出React / Redux的最佳实践。

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

[{
  label: 'a',
  value: 10
}, {
  label: 'b',
  value: 6
}, ...]
Run Code Online (Sandbox Code Playgroud)

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

{
  a: {
    value1: 15,
    value2: 3,
    value3: 7,
    ...
  },
  b: { ... }
}
Run Code Online (Sandbox Code Playgroud)

现在我必须做一些计算,得到的结果数据(如值1 -value2 +值3 ...也许一些过滤器...),问题是,我应该把这个计算在减速(我觉得它更像是,将其作为道具通过传递给组件connect(如getCartProducts 本例中所示)或容器组件(在这种情况下可能是仪表板)?

我认为两种选择都有意义:

  • 在reducer中:我们可以保持组件清洁,并将所有逻辑放在同一位置。

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

如果我选择减速机,则会出现另一个问题。我应该将计算的数据保存在存储中吗?或者只是保存源数据,并在每次渲染组件时进行计算?旧的React文档说您不应该将计算的数据保存在状态中,不确定Redux是否为true。

Kok*_*lav 5

通常:

  1. 存储应包括最小可能状态。

  2. 通过reselect在mapStateToProps中计算派生数据,以记忆结果。计算将立即被调用;

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

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

例如通过选择器计算:

用于选择器组成,以避免在更新过滤器时重新计算:

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))
);
Run Code Online (Sandbox Code Playgroud)

const mapStateToProps=(state)=>{
  return {
    chartData:getItemsForChartWithFilter(state)
  };
};
Run Code Online (Sandbox Code Playgroud)

不能保证收集中的顺序,因此,除了收集外,也许您还应该从服务器阵列中接收密钥。然后代码会有所不同...