我有一个SectionList,其中填充了Firebase中的数据。该列表显示按日期划分的事件信息,当前月份显示为THIS MONTH
,其他日期使用其简写值JAN
,FEB
等。
我得到的数据很好,并且可以很好地显示,但是我不知道如何按日期对数据数组进行分组。仅供参考,日期以日期字符串'2019-01-05
'的形式保存在数据库中,我使用一下矩通过以下方法对其进行格式化:
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
哪个返回JAN
。我运行一个简单的if
语句来检查当前月份的title值,并用时刻对其进行格式化,如果匹配,则将title的显示名称更改为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
});
标题是月份名称,我需要对它进行排序和分组。
这是当前的外观:
我希望同一月份的每个活动都在同一部分下。
任何帮助都将是惊人的!
完整组件:
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>
);
}
}
答案 0 :(得分:2)
我认为您不关心分组的年份,因为在这种情况下,2018-01和2019-01都是JAN。但是无论如何,请看下面的示例,我试图注释代码中的每个步骤:
// define your flat list of events
const events = [
{name: 'dummy one', date: '2019-01-05'},
{name: 'dummy some', date: '2019-02-04'},
{name: 'dummy another', date: '2019-01-07'},
{name: 'dummy really dummy', date: '2019-04-05'},
{name: 'dummy and funny', date: '2019-06-05'},
{name: 'dummy not funny', date: '2019-06-22'}
].sort((a, b) => a.date < b.date ? -1 : 1)
// remember to sort them early so you will not have to worry about it anytime later on
// extract distinct names from available events, we are using Set constructor to make sure any key won't be doubled and also that there won't be any empty month
const groupNames = Array.from(new Set(events.map(k => k.date.split('-')[1]))) // split date by hyphen and return only month part
// define place for groups
let groups = {}
// create groups containers from names
groupNames.forEach(k => {
groups[k] = []
})
// iterate by events and attach every to given group based on its month
events.forEach(k => {
const month = k.date.split('-')[1]
groups[month].push(k)
})
// container for demo purposes
let resultHTML = ''
// iterate by groups, if you are unsure about 'for in' loop, use groupNames for that part, and then iterate by events in every group
for(let key in groups) {
resultHTML += `<h2>${key}</h2>`
for (let event of groups[key]) {
resultHTML += `<p>${event.date} — ${event.name}</p>`
}
}
// display results for demo purposes
document.querySelector('.result').innerHTML = resultHTML
<div class="result"></div>