0

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 component notifications.jsx

export class CompanyNotifications extends Component {
    constructor(props) {
        super(props);
        this.state = { contacts: [],    sort: {
            direction: 'desc',
          } };

      compareBy(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.compareBy(key));
        this.setState({contacts: arrayCopy});

        if (direction === 'asc') {
            arrayCopy.reverse();
          }

          this.setState({
            data: arrayCopy,
            sort: {
              direction,
            }
          });
      }

Fetched the data when component mount, by default data is in ascending order

      componentDidMount() {
        fetch('../companyNotifications.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 
5
  • 1
    its not readable, format this code, add it to jsFiddle or sandbox 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 comparison operators it gives you. a.isBefore(b), a.isAfter(b), a.isSameOrBefore(b), a.isSameOrAfter(b). Google Moment.js and check out the docs. Commented Sep 4, 2019 at 20:22
  • 1
    @Brant Moment.js has quite a big bundle size and pulling it in just for comparing 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. 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. :) Commented Sep 4, 2019 at 21:01
  • Thank you. I used mement js just for date field. And it works Commented Sep 4, 2019 at 21:37

2 Answers 2

3

It's doing a string comparison - so it's not sorting it as dates. Try changing your sort for date to:

componentDidMount() {
    fetch('../companyNotifications.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)
  }
Sign up to request clarification or add additional context in comments.

Comments

2

You are actually not sorting dates but strings. As your strings start with the month and "0" comes before "1" this will work.

But as years are more significant for sorting dates your approach doesn't work if the year comes last in your string representation of it.

Your either need to change the representation to have the year come first, then the month and then the day. Or you need to first transform them to real Date objects before comparing them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.