I am displaying list of data sorted by date from JSON using ReactJS. My code only sorts the data by date and month only, but it does not take the year.
It works fine for other fields such as {contact.agencyEmail, contact.messageT, contact.message}
How do I make this code to sort by date.
This is my ponent notifications.jsx
export class CompanyNotifications extends Component {
constructor(props) {
super(props);
this.state = { contacts: [], sort: {
direction: 'desc',
} };
pareBy(key) {
return function (a, b) {
if (a[key] < b[key]) return -1;
if (a[key] > b[key]) return 1;
return 0;
};
}
Sorting for Assending and descending order
``` sortBy(key) {
const direction = this.state.sort ? (this.state.sort.direction === 'asc' ? 'desc' : 'asc') : 'desc';
let arrayCopy = [...this.state.contacts];
arrayCopy.sort(thispareBy(key));
this.setState({contacts: arrayCopy});
if (direction === 'asc') {
arrayCopy.reverse();
}
this.setState({
data: arrayCopy,
sort: {
direction,
}
});
}
Fetched the data when ponent mount, by default data is in ascending order
ponentDidMount() {
fetch('../panyNotifications.json')
.then(res => res.json())
.then((data) => {
data.sort((a,b) => a.dateCreated.localeCompare(b.dateCreated));
this.setState({ contacts: data })
.then(data => this.setState({ contacts: data }));
})
.catch(console.log)
}
render() {
const Contacts = ({ contacts }) => {
return (
<div class="table-container">
<table>
<thead>
<tr class="table100-head">
<th class="column1" onClick={() => this.sortBy('dateCreated')}>Date Created<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column2" onClick={() => this.sortBy('agencyEmail')}>Agency Email<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column3" onClick={() => this.sortBy('messageT')}>Message Type<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column4">Message</th>
</tr>
</thead>
<tbody>
{contacts.map((contact) => (
<tr>
<td class="column1">{contact.dateCreated}</td>
<td class="column2">{contact.agencyEmail}</td>
<td class="column3">{contact.messageT}</td>
<td class="column4">{contact.message}</td>
</tr>
))}
</tbody>
</table>
</div>
)
};
}
}
This is the result i'm getting from my code
>01/12/2019
>01/13/2018
>02/22/2019
>06/30/2019
>07/17/2019
>10/02/2019
>11/01/2019
but I'm expecting
>01/12/2019
>02/22/2019
>06/30/2019
>07/17/2019
>10/02/2019
>11/01/2019
>01/13/2018
I am displaying list of data sorted by date from JSON using ReactJS. My code only sorts the data by date and month only, but it does not take the year.
It works fine for other fields such as {contact.agencyEmail, contact.messageT, contact.message}
How do I make this code to sort by date.
This is my ponent notifications.jsx
export class CompanyNotifications extends Component {
constructor(props) {
super(props);
this.state = { contacts: [], sort: {
direction: 'desc',
} };
pareBy(key) {
return function (a, b) {
if (a[key] < b[key]) return -1;
if (a[key] > b[key]) return 1;
return 0;
};
}
Sorting for Assending and descending order
``` sortBy(key) {
const direction = this.state.sort ? (this.state.sort.direction === 'asc' ? 'desc' : 'asc') : 'desc';
let arrayCopy = [...this.state.contacts];
arrayCopy.sort(this.pareBy(key));
this.setState({contacts: arrayCopy});
if (direction === 'asc') {
arrayCopy.reverse();
}
this.setState({
data: arrayCopy,
sort: {
direction,
}
});
}
Fetched the data when ponent mount, by default data is in ascending order
ponentDidMount() {
fetch('../panyNotifications.json')
.then(res => res.json())
.then((data) => {
data.sort((a,b) => a.dateCreated.localeCompare(b.dateCreated));
this.setState({ contacts: data })
.then(data => this.setState({ contacts: data }));
})
.catch(console.log)
}
render() {
const Contacts = ({ contacts }) => {
return (
<div class="table-container">
<table>
<thead>
<tr class="table100-head">
<th class="column1" onClick={() => this.sortBy('dateCreated')}>Date Created<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column2" onClick={() => this.sortBy('agencyEmail')}>Agency Email<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column3" onClick={() => this.sortBy('messageT')}>Message Type<FontAwesomeIcon aria-hidden="true" icon={faSort}/></th>
<th class="column4">Message</th>
</tr>
</thead>
<tbody>
{contacts.map((contact) => (
<tr>
<td class="column1">{contact.dateCreated}</td>
<td class="column2">{contact.agencyEmail}</td>
<td class="column3">{contact.messageT}</td>
<td class="column4">{contact.message}</td>
</tr>
))}
</tbody>
</table>
</div>
)
};
}
}
This is the result i'm getting from my code
>01/12/2019
>01/13/2018
>02/22/2019
>06/30/2019
>07/17/2019
>10/02/2019
>11/01/2019
but I'm expecting
>01/12/2019
>02/22/2019
>06/30/2019
>07/17/2019
>10/02/2019
>11/01/2019
>01/13/2018
Share
asked Sep 4, 2019 at 20:17
Ayoob NazeerAyoob Nazeer
91 silver badge4 bronze badges
5
- 1 its not readable, format this code, add it to jsFiddle or sandbox – Vasyl Gutnyk Commented Sep 4, 2019 at 20:20
- My go-to for anything date related in Moment.js. Use moment on each of your dates and then use the parison operators it gives you. a.isBefore(b), a.isAfter(b), a.isSameOrBefore(b), a.isSameOrAfter(b). Google Moment.js and check out the docs. – Brant Commented Sep 4, 2019 at 20:22
-
1
@Brant Moment.js has quite a big bundle size and pulling it in just for paring dates is quite an overkill. This can be done with built-in functions. If it really needs to be done with a library I'd pick
date-fns
instead which is much smaller and allows for tree shaking. – trixn Commented Sep 4, 2019 at 20:31 - That's correct. Seeing as I tend to work on larger apps that already have some reliance on Moment, it's already there to use. I take that for granted sometimes. :) – Brant Commented Sep 4, 2019 at 21:01
- Thank you. I used mement js just for date field. And it works – Ayoob Nazeer Commented Sep 4, 2019 at 21:37
2 Answers
Reset to default 3It's doing a string parison - so it's not sorting it as dates. Try changing your sort for date to:
ponentDidMount() {
fetch('../panyNotifications.json')
.then(res => res.json())
.then((data) => {
data.sort((a,b) => new Date(a) < new Date(b) ? 1 : -1);
this.setState({ contacts: data })
.then(data => this.setState({ contacts: data }));
})
.catch(console.log)
}
You are actually not sorting dates but strings. As your strings start with the month and "0"
es before "1"
this will work.
But as years are more significant for sorting dates your approach doesn't work if the year es last in your string representation of it.
Your either need to change the representation to have the year e first, then the month and then the day. Or you need to first transform them to real Date
objects before paring them.