Search code examples
javascriptreactjsdatatablesortables

How to sort table by asc and desc all field in React js


I am building a simple app in ReactJS that works with a JSON array by calling a certain API. I am then populating the results of the array in a table. I now wanted to make the columns of the table sortable . What I ideally want is to have both ascending and descending sorting. Once I click on the header when it is sorted ascending, it should sort descending and vice-versa.but problem is its working only one time not working like both asc and desc order so how to do to this in both asc and desc. Here is my code.

import React, { Component } from "react";
import "./styles.css";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      driver: []
    };
  }

  async componentDidMount() {
    try {
      const res = await fetch(`https://digitalfleet.eu/api/1/drivers/`);
      const driver = await res.json();
      console.log(driver);
      this.setState({
        driver
      });
    } catch (e) {
      console.log(e);
    }
  }

  compareBy(key) {
    return function (a, b) {
      if (a[key] < b[key]) return -1;
      if (a[key] > b[key]) return 1;
      return 0;
    };
  }

  sortBy(key) {
    let arrayCopy = [...this.state.driver ];
    arrayCopy.sort(this.compareBy(key));
    this.setState({driver: arrayCopy});
  }

  render() {
    const { driver } = this.state;
    return (
      <div className="App">
        <table className="table table-hover">
          <thead>
            <tr className="th ">
              <th style={{ width: "5%" }}>id</th>
              <th>Name</th>
              <th className="">Car</th>
              <th className="" onClick={() => this.sortBy('milage')}>Milage </th>
              <th className="">Fuel Consumed</th>
              <th className="">Average Fuel</th>
              <th className="" onClick={() => this.sortBy('overspeeding_distance')}>Overspeeding Distance</th>
              <th onClick={() => this.sortBy('critical_overspeed')}>Critical Speed</th>
              <th onClick={() => this.sortBy('overallscore')}>Score</th>
            </tr>
          </thead>
          <tbody>
            {/* currPage.data */}
            {driver.map((c, i) => (
              <tr key={c.pk}>
                <td>{i + 1}</td>
                <td style={{ color: "#b71c1c" }} className="font-weight-bolder">
                  {c.name ? `${c.name}` : " ? "}
                  {/* </a> */}
                </td>
                <td>{c.carquanttity ? `${c.carquanttity}` : "-"} </td>
                <td>{c.milage ? `${c.milage.toFixed(1)}` : "-"} </td>
                <td>
                  {c.fuel_consumed ? `${c.fuel_consumed.toFixed(1)}` : "-"}
                </td>
                <td>
                  {c.average_fuel_consumed
                    ? `${c.average_fuel_consumed.toFixed(1)}`
                    : "-"}{" "}
                </td>
                <td>
                  {c.overspeeding_distance
                    ? `${c.overspeeding_distance.toFixed(1)}`
                    : "-"}
                </td>
                <td>
                  {c.critical_overspeed
                    ? `${c.critical_overspeed.toFixed(1)}`
                    : "-"}
                </td>
                <td>
                  {c.overallscore ? `${c.overallscore.toFixed(1)}` : " - "}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }
}

export default App;

And here is codesanbox link of my code. https://codesandbox.io/s/pensive-mountain-i259j


Solution

  • You have written same sort functionality for both ascending and desc while it should return different type in both cases.

    without maintaining additional flag I fixed it .Check this out Visit https://codesandbox.io/s/pensive-engelbart-i6n2y