You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在map函数中正确渲染按日期分组的JSX元素

问题描述

我有如下对象数组形式的数据:

history = [
  {item: cake, calories: 120, datetime: '2022-11-16 07:51:26'},
  {item: chicken, calories: 250, datetime: '2022-11-16 13:48:46'},
  {item: pizza, calories: 420, datetime: '2022-11-25 11:13:42'}
];

我希望渲染一个包含日期标题的div,并将同一日期的所有项归组到列表中。我尝试用map函数实现:

第一次尝试的代码:

function renderHistory () {
  let date;

  return props.history.map((item, i) => {
    const dateAdded = item.datetime.split(" ")[0];

    if (date !== dateAdded) {
      date = dateAdded;
      return (
        <>
          <div>
            <h2>{dateAdded}</h2>
            <li>{item.item} - {item.calories} calories</li>
        </>
      )
    }

    return (
      <>
          <li>{item.item} - {item.calories} calories</li>
        </div>
      </>
    )

  })
}

出现错误:Expected corresponding JSX closing tag for <div>

第二次修改后的代码:

return props.history.map((item, i) => {

  const dateAdded = item.datetime.split(" ")[0];

  if (date !== dateAdded) {
    date = dateAdded;
    return (
      <div>
        <h2>{dateAdded}</h2>
        <li>{item.item} - {item.calories} calories</li>
      </div>
    )
  }

  return (
    <li>{item.item} - {item.calories} calories</li>
  )

})

但同日期的第二个元素会跳出div,请问如何将同一日期的所有项放入同一个div中?


解决方案

直接遍历原数组无法实现同日期元素的容器合并,正确做法是先按日期分组数组,再基于分组后的数据渲染UI。

1. 按日期分组数组

先写一个工具函数,将原数组按日期字段分组:

const groupHistoryByDate = (history) => {
  return history.reduce((groups, item) => {
    const date = item.datetime.split(" ")[0];
    // 如果当前日期还没创建分组,初始化一个空数组
    if (!groups[date]) {
      groups[date] = [];
    }
    // 将当前项加入对应日期的分组
    groups[date].push(item);
    return groups;
  }, {});
};

这个函数会把原数组转换成如下结构的对象:

{
  "2022-11-16": [
    {item: cake, calories: 120, datetime: '2022-11-16 07:51:26'},
    {item: chicken, calories: 250, datetime: '2022-11-16 13:48:46'}
  ],
  "2022-11-25": [
    {item: pizza, calories: 420, datetime: '2022-11-25 11:13:42'}
  ]
}

2. 渲染分组后的UI

修改renderHistory函数,先分组再渲染:

function renderHistory(props) {
  const groupedData = groupHistoryByDate(props.history);
  
  // 将分组对象的日期键转换为数组,方便遍历
  return Object.keys(groupedData).map(date => (
    <div key={date}>
      <h2>{date}</h2>
      <ul> {/* 注意:li必须包裹在ul/ol内,符合HTML语义规范 */}
        {groupedData[date].map((item, index) => (
          <li key={index}>{item.item} - {item.calories} calories</li>
        ))}
      </ul>
    </div>
  ));
}

关键说明

  • 用reduce分组是处理这类归组需求的标准方案,逻辑清晰且易于维护,比直接遍历原数组更可靠。
  • 每个日期对应一个独立的div容器,内部包含日期标题和该日期下的所有食物列表,完全满足同日期项归组的需求。
  • 补充了<ul>标签包裹<li>,避免出现无效的DOM结构,符合HTML规范。

内容的提问来源于stack exchange,提问作者DragonBorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:10:32