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

React Native中FlatList多事件日期仅显示一次的实现问询

解决React Native FlatList中多事件日期重复显示的问题

这个问题我做日程类APP时也碰到过,核心思路要么是先把事件按日期分组,要么是渲染时判断当前项与前一项的日期是否重复,给你两种靠谱的实现方案:

方案一:先对事件按日期分组(推荐)

这种方法逻辑更清晰,也能避免FlatList组件复用带来的异常,步骤如下:

1. 处理原事件数组,按日期分组

先写一个函数把同一天的事件归为一组,用统一格式的日期作为分组key:

import moment from 'moment';

// 按日期分组事件
const groupEventsByDate = (events) => {
  return events.reduce((groupedData, event) => {
    // 用YYYY-MM-DD作为统一的日期key,确保同一天的事件分到一组
    const dateKey = moment(event.start.dateTime).format('YYYY-MM-DD');
    if (!groupedData[dateKey]) {
      groupedData[dateKey] = [];
    }
    groupedData[dateKey].push(event);
    return groupedData;
  }, {});
};

// 把分组后的对象转成FlatList可用的数组格式
const formattedEvents = Object.entries(groupEventsByDate(yourOriginalEvents)).map(([date, events]) => ({
  date,
  eventsList: events
}));

2. 修改FlatList的渲染逻辑

现在FlatList的数据源是分组后的数组,每个元素包含日期和对应事件列表,渲染时先显示一次日期,再渲染该日期下的所有事件:

const renderItem = ({ item }) => {
  const eventDate = moment(item.date);
  // 正确判断是否为今天(原代码直接比较moment对象是错误的,要用isSame方法)
  const isToday = eventDate.isSame(moment(), 'day');
  const dateStyle = isToday ? styles.today : undefined;

  return (
    <View style={styles.groupContainer}>
      {/* 只显示一次日期标题 */}
      <Text style={[styles.dateTitle, dateStyle]}>
        {eventDate.format('MM月DD日')} {/* 这里可以自定义日期显示格式 */}
      </Text>
      {/* 渲染该日期下的所有事件 */}
      {item.eventsList.map((event, idx) => (
        <View key={idx} style={styles.eventItem}>
          {/* 这里放你的事件内容,比如标题、时间等 */}
          <Text style={styles.eventTitle}>{event.summary}</Text>
          <Text style={styles.eventTime}>
            {moment(event.start.dateTime).format('HH:mm')}
          </Text>
        </View>
      ))}
    </View>
  );
};

// 最后FlatList的用法
<FlatList
  data={formattedEvents}
  renderItem={renderItem}
  keyExtractor={(item) => item.date}
/>

方案二:不分组,渲染时判断日期是否重复

如果不想修改数据源结构,可以在渲染时对比当前项和前一项的日期,相同则隐藏日期:

import { useRef } from 'react';

// 用useRef存储上一个项的日期,避免组件复用导致的异常
const prevDateRef = useRef(null);

const renderRow = ({ item, index }) => {
  const currentDate = moment(item.start.dateTime).format('YYYY-MM-DD');
  const isToday = moment(currentDate).isSame(moment(), 'day');
  const dateStyle = isToday ? styles.today : undefined;

  // 判断是否需要显示日期:当前日期和上一个不同,或者是第一项
  const shouldShowDate = !prevDateRef.current || currentDate !== prevDateRef.current;

  // 更新上一个日期的引用
  if (shouldShowDate) {
    prevDateRef.current = currentDate;
  }

  return (
    <View style={styles.eventRow}>
      {/* 只有需要显示时才渲染日期 */}
      {shouldShowDate && (
        <Text style={[styles.dateText, dateStyle]}>
          {moment(currentDate).format('MM月DD日')}
        </Text>
      )}
      <View style={styles.eventContent}>
        {/* 你的事件内容 */}
        <Text>{item.summary}</Text>
      </View>
    </View>
  );
};

重要注意事项

  • 原代码里的moment() == eventdate是错误的,moment对象是引用类型,直接比较不会相等,必须用isSame方法并指定比较维度(比如'day')来判断是否为同一天。
  • 方案二更适合简单场景,但如果FlatList有大量数据或启用了组件复用,可能会出现日期显示异常,所以优先推荐方案一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:44:00