Search code examples
reactjsrenderingreact-on-rails

React: Rendering based on date order


I have a form which renders and inserts a component into a timeline, but I can't figure out how to get it to render a new submission chronologically, so that it gets inserted in the correct order.

This is what I've been trying so far.

render() {
  return (
    <div className="timeline-container">
      <ul>
        {this.state.activities
          .sort((a, b) => a.date > b.date)
          .map((activity, i) => (
            <Activity
              key={i}
              data={activity}
              handleDelete={this.handleDelete}
            />
          ))}
      </ul>
    </div>
  );
}

And this is the Activity component:

<li>
  <span></span>
  <div className="activity-title">{this.state.activity.title}</div>
  <div className="activity-info">{this.state.activity.description}</div>
  <div className="activity-location">{this.state.activity.location}</div>
  <div className="activity-date">{this.state.activity.date.slice(0, 10)}</div>
  <button onClick={this.handleDelete.bind(this, this.state.activity.id)}>
    Delete
  </button>
</li>;

At the moment it is still automatically rendering when the form is submitted, but it isn't sorting them.


Solution

  • You should be using new Date(date).getTime() method to compare and sort. A best way to do is:

    .sort(
      (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
    )
    

    And with my dummy data I get this:

    preview

    I have added some more entries and here's a full code:

    const Activity = props => (
      <li>
        {props.data.title} (#{props.data.id}) ({props.data.date.split("T")[0]})
      </li>
    );
    
    class App extends React.Component {
      state = {
        activities: [
          {
            id: 1,
            trip_id: 5,
            title: "Activity 1",
            description: "Description 1",
            location: "Location 1",
            date: "2019-07-03T23:00:00.000Z",
            pending: null,
            created_at: "2019-07-28T17:49:40.269Z",
            updated_at: "2019-07-28T17:49:40.269Z"
          },
          {
            id: 2,
            trip_id: 5,
            title: "Activity 2",
            description: "Description 1",
            location: "Location 1",
            date: "2019-07-05T23:00:00.000Z",
            pending: null,
            created_at: "2019-07-28T17:49:40.269Z",
            updated_at: "2019-07-28T17:49:40.269Z"
          },
          {
            id: 3,
            trip_id: 5,
            title: "Activity 3",
            description: "Description 1",
            location: "Location 1",
            date: "2019-07-02T23:00:00.000Z",
            pending: null,
            created_at: "2019-07-28T17:49:40.269Z",
            updated_at: "2019-07-28T17:49:40.269Z"
          }
        ]
      };
      render() {
        return (
          <div className="timeline-container">
            <ul>
              {this.state.activities
                .sort(
                  (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
                )
                .map((activity, i) => (
                  <Activity
                    key={i}
                    data={activity}
                    handleDelete={this.handleDelete}
                  />
                ))}
            </ul>
          </div>
        );
      }
    }
    

    Here in this example, I have used more than one activity to show you how they are sorted by date.

    Demo: CodeSandbox