I have a SectionList which I populate with data from firebase. The list shows event info sectioned by date, with the current month visible as THIS MONTH and the other dates using their shorthand value of JAN, FEB etc..
I get the data fine and can display it fine but I can't figure out how to group the data array by the dates. FYI the dates are saved in the db as date strings '2019-01-05' and i use moment to format them with this method:
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
Which returns JAN. I run a simple if statement to check the value of title against the current month which I format with moment and if its a match I change the display name of title to THIS MONTH.
The data is pushed to an array like so:
listData.push({
data: [
{
id: event,
eventName: eventObj.eventName,
location: eventObj.location,
description: eventObj.description,
creatorsName: eventObj.creatorsName,
date: eventObj.date,
discipline: eventObj.discipline
}
],
title
});
With the title being the month name and the key that I need to sort and group this by.
This is how it currently looks:
This is how I would like it to look: (used dummy data to present it correctly)

I would like each event that is in the same month to be under the same section.
Any help would be amazing!
FULL COMPONENT:
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>
);
}
}
