我正在从事一个中型到大型的 React/redux 项目,我正在尝试找出 React/Redux 的最佳实践。
例如,如果我有一个饼图组件,它将采用一个简单的数组作为属性:
[{
label: 'a',
value: 10
}, {
label: 'b',
value: 6
}, ...]
但是我从API服务器获取的源数据可能是这样的:
{
a: {
value1: 15,
value2: 3,
value3: 7,
...
},
b: { ... }
}
现在我必须做一些计算来获得结果数据(比如 value1 -value2 + value3... 可能是一些过滤器...),问题是,我应该把这个计算放在 reducer中吗strong>(我觉得它更像是一个 getter,它将通过 connect
作为 prop 传递给一个组件,例如 getCartProducts
in this example ),或者一个容器组件(在这种情况下可能是一个仪表板)?
我认为这两种选择都有意义:
在 reducer 中:我们可以保持我们的组件干净,并将所有逻辑放在同一个地方。
在容器中:因为是UI相关的,如果计算出来的数据是不可复用的(只针对那个饼图),我们可以把这种计算保留在相关的组件中。
如果我选择 reducer ,那么另一个问题来了。我应该将计算后的数据保存在商店中吗?或者只是保存源数据,并在每次渲染组件时计算它? The old React doc说你不应该在状态中保存计算数据,不确定 redux 是否正确。
最佳答案
通常:
store 应该包含尽可能少的状态。
派生数据是通过 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)
};
};
顺便说一下,集合中的顺序是无法保证的,因此除了集合之外,您也许还应该从服务器接收键数组。然后代码会有点不同...
关于javascript - React + Redux,我的 UI 相关的计算应该去哪里,容器组件,还是 reducer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41117309/