处理redux中数据计算和格式化的最佳方法

时间:2017-03-27 09:08:49

标签: reactjs redux react-redux

我有一个相当简单的要求,即在我的Javascript应用程序中呈现开始/结束日期表:

<table>
   <tr>
      <th>Start Date</th>
      <th>End Date</th>
      <th>Number of weeks</th>
   </tr>
   <tr>
      <td>2 Jan 2017</td>
      <td>9 Jan 2017</td>
      <td>1</td>
   </tr>
   <!-- etc -->
 </table>

我的原始数据如下所示:

[
    {
       Id: 8672,
       StartDate: "2017-01-02",
       Weeks: 1
    }
    // More rows
]

我的问题是,执行这些字段的计算和格式化的最佳方法是什么,以便保持关注点的分离而不会对性能产生负面影响?我考虑了很多方法:

在数据存储到数据存储之前对其进行转换

我可以使用reducer函数或引发“数据加载”操作的代码片段将原始数据映射到更接近UI Component所需格式和字段的内容。这样做的好处是可以简化UI组件,但它确实将数据和减速器与用户界面控件紧密联系在一起。

执行计算&amp; UI组件中的格式设置

我可以在用户UI组件中格式化和解析数据。这似乎是个坏主意,因为它将UI组件与数据格式紧密联系在一起。

在表格UI的mapStateToProps中执行转换

这似乎是一种很好的方法,但它会强制react-redux绑定在每次状态更改时重新呈现整个表,因为每次渲染都会导致dates道具具有不同的身份

const datesRow = (date) => (
    <tr>
       <td>{date.StartDate}</td>
       <td>{date.EndDate}</td>
       <td>{date.NumberOfWeeks}</td>
    </tr>
)

const datesTable = ({dates}) => (
    <table>
      <tr>
        <th>Start Date</th>
        <th>End Date</th>
        <th>Number of weeks</th>
      </tr>
      { dates.map(datesRow) }
    </table>
);

const mapStateToProps = (state) => ({
  dates: state.dates.map(x => transformDates(x))
});

const DatesTableContainer = connect(mapStateToProps)(datesTable);

制作行UI组件并在那里进行映射

这似乎维持了之前选项提供的UI和状态之间的松散耦合,但也允许UI的增量更新。容器上看起来很重。这是个好主意吗?

const datesRow = (date) => (
    <tr>
       <td>{date.StartDate}</td>
       <td>{date.EndDate}</td>
       <td>{date.NumberOfWeeks}</td>
    </tr>
)

const mapStateToPropsForRow = (state, ownProps) => {
  const dateItem = lookupDateById(ownProps.dateId);
  return {
      StartDate: formatDate(dateItem.StartDate),
      EndDate: calculateAndFormatEndDate(dateItem.EndDate),
      NumberOfWeeks: dateItem.NumberOfWeeks
  }
};

const DatesRowContainer = connect(mapStateToPropsForRow)(datesRow);

const mapStateToPropsForRow = (state, ownProps) => {
  const dateItem = lookupDateById(ownProps.dateId);
  return {
      StartDate: formatDate(dateItem.StartDate),
      EndDate: calculateAndFormatEndDate(dateItem.EndDate),
      NumberOfWeeks: dateItem.NumberOfWeeks
  }
};

const datesTable = ({id}) => (
    <table>
      <tr>
        <th>Start Date</th>
        <th>End Date</th>
        <th>Number of weeks</th>
      </tr>
      <DatesRowContainer dateId={id} />
    </table>
);

const mapStateToPropsForTable = (state) => ({
  dates: state.dates.map(x => {id: x.id})
});

const DatesTableContainer = connect(mapStateToPropsForTable)(datesTable);

1 个答案:

答案 0 :(得分:1)

最好的方法可能是在你的减速机中重新映射它。在那里,它只需要完成一次,而不是在每个渲染上执行,如果你要在mapStateToProps - 或render - 函数中重新映射它。您的数据获取(或从任何来源加载数据)已经是&#34; 慢动作&#34;无论如何,所以如果在那里添加重新映射,就不会打扰用户。

在最后两个中的任何一个中,您可能会使应用程序断断续续,特别是如果您的数据集很大或重新映射都很昂贵。 然而,每次重新报复都是不合理的。

或者您可以使用reselect库,但我自己还没有使用它,所以我无法对此发表任何评论。