我有一个部分列表,其中填充了来自 firebase 的数据。该列表显示按日期划分的事件信息,当前月份显示为THIS MONTH
和其他日期使用其速记值JAN
, FEB
etc..
我得到的数据很好并且可以很好地显示它,但我不知道如何按日期对数据数组进行分组。仅供参考,日期作为日期字符串保存在数据库中'2019-01-05
',我用这个方法来格式化它们:
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
哪个返回JAN
。我运行一个简单的if
语句来检查标题值与当前月份的值,我用 moment 格式化它,如果匹配,我将标题的显示名称更改为THIS MONTH
.
数据被推送到数组中,如下所示:
listData.push({
data: [
{
id: event,
eventName: eventObj.eventName,
location: eventObj.location,
description: eventObj.description,
creatorsName: eventObj.creatorsName,
date: eventObj.date,
discipline: eventObj.discipline
}
],
title
});
标题是月份名称和我需要对其进行排序和分组的键。
这是它目前的样子:
This is how I would like it to look: (used dummy data to present it correctly)
我希望同一个月内的每个活动都位于同一部分下。
任何帮助都会很棒!
完整组件:
import React from 'react';
import {View, StyleSheet, SectionList, TouchableOpacity} from 'react-native';
import { Container, Content , Text, Icon, Spinner } from 'native-base';
import Collapsible from 'react-native-collapsible';
import {f, auth, database} from '../../config/config';
import _ from 'lodash';
import CustomIcon from '../utilities/CustomIcon';
import Month from './Month';
import moment from 'moment';
import Day from './Day';
let today = moment();
let now = today.format("YYYY-MM-DD");
let getCurrentMonth = today.month('MMM');
const monthOrder = [
'JAN',
'FEB',
'MAR',
'APR',
'MAY',
'JUN',
'JUL',
'AUG',
'SEPT',
'OCT',
'NOV',
'DEC'
];
class SectionListItem extends React.Component {
state = {
descriptionCollapsed: true
};
toggleDescription = () => {
this.setState({ descriptionCollapsed: !this.state.descriptionCollapsed
});
};
render() {
let fullDay = moment(this.props.item.date);
fullDay.day();
const day = fullDay.format('DD')
return (
<View style={styles.sectionListItemContainer}>
<View style={styles.eventInfoContainer}>
<View>
<Day day={day}/>
</View>
<TouchableOpacity onPress={this.toggleDescription}>
<View style={styles.info}>
<Text style={styles.eventName}>{this.props.item.eventName.toUpperCase()}</Text>
<Text style={styles.creatorsName}>Coached by {this.props.item.creatorsName}</Text>
<Text style={styles.location}>{this.props.item.location}</Text>
</View>
</TouchableOpacity>
</View>
<Collapsible collapsed={this.state.descriptionCollapsed}>
<EventDescription description={this.props.item.description} discipline={this.props.item.discipline}/>
</Collapsible>
</View>
);
}
}
class EventDescription extends React.Component {
render() {
return (
<View style={styles.descriptionDropdown}>
<View >
<Icon name='arrow-up' type="SimpleLineIcons" style={styles.upArrow} />
</View>
<View style={styles.descriptionContainer}>
<Text style={styles.description}>{this.props.description}</Text>
</View>
<View style={styles.iconContainer}>
{!!this.props.discipline ? (this.props.discipline.map((item, index) => {
return <View key={index} style={styles.iconMargin}><CustomIcon name={item} size={20} style={styles.iconStyle}/></View>
})) : null}
</View>
</View>
);
}
}
class SectionHeader extends React.Component {
render() {
return (
<View style={styles.monthHeader}>
<Month month={this.props.section.title}/>
</View>
);
}
}
export default class EventList extends React.Component {
constructor(props) {
super(props);
this.state = {
filterCollapsed: true,
listData: [],
loading: true,
refreshing: false
}
}
componentDidMount() {
this.loadEvents();
}
onRefresh = () => {
this.setState({refreshing: true})
this.loadEvents();
}
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
getDateMatches = (date) => {
return database
.ref('events')
.orderByChild('date')
.startAt(date)
.once("value")
.then((snapshot) => {
let matches = [];
snapshot.forEach((child) => {
let val = child.val();
const valMonth = this.formatDateToMonth(val.date);
const dateMonth = this.formatDateToMonth(date);
if (dateMonth === valMonth) {
matches.push(val);
}
});
return matches;
});
}
loadEvents = () => {
this.setState({listData: []});
const that = this;
database.ref('events').once('value').then((snapshot) => {
const exists = (snapshot.val() !== null);
if (exists) {
data = snapshot.val();
}
const listData = that.state.listData;
let monthData = {title: '', data: []};
const thisMonth = { title: 'THIS MONTH', data: []};
const otherMonth = { title: '', data: []};
for(var event in data) {
const eventObj = data[event];
const month = this.formatDateToMonth(eventObj.date);
let title;
getCurrentMonth.month();
const currentMonth = getCurrentMonth.format('MMM');
if (month === currentMonth.toUpperCase()) {
title = 'THIS MONTH';
} else {
title = month;
}
listData.push(
{
data: [
{
id: event,
eventName: eventObj.eventName,
location: eventObj.location,
description: eventObj.description,
creatorsName: eventObj.creatorsName,
date: eventObj.date,
discipline: eventObj.discipline,
}
],
title
}
);
// listData.sort((a, b) => {
// return (a.title - b.title) || (monthOrder.indexOf(a.title) - monthOrder.indexOf(b.title))
// });
that.setState({loading: false, refreshing: false});
}
}).catch(error => console.log('error: ', error));
}
toggleFilter = () => {
this.setState({ filterCollapsed: !this.state.filterCollapsed });
};
render() {
if (!!this.state.loading) {
return (
<View style={styles.spinner}>
<Spinner color="#81e6fc"/>
</View>
)
}
return (
<Container style={styles.container}>
<TouchableOpacity style={styles.filterTextContainer} onPress={this.toggleFilter}>
<Text style={styles.filterText}>FILTER</Text>
</TouchableOpacity>
<Collapsible collapsed={this.state.filterCollapsed}>
<CustomIcon name="Rate" size={50} style={styles.iconStyle}/>
</Collapsible>
<Content contentContainerStyle={styles.list}
onRefresh={this.onRefresh}
refreshing={this.state.refreshing}
>
<SectionList
renderItem={({item, index}) => {
return <SectionListItem item={item} index={index}/>
}}
renderSectionHeader={({section}) => {
return <SectionHeader section={section}/>
}}
sections={dummyData}
keyExtractor={(item, index) => item + index}
>
</SectionList>
</Content>
</Container>
);
}
}