1

I am trying to sort the table data based on the field selected from the dropdown. It should alternatively sort between ascending or descending whenever the same field is clicked. I am maintaining a sort object that decides which field is selected and what is the sort order. Then it is sent to lodash orderBy with the field and the order. It does not work

This is what I have tried. Can some one tell me what I am doing wrong. Help is really appreciated.

https://codesandbox.io/s/simple-react-class-component-1n3f9?file=/src/index.js:0-3000

import React from "react";
import ReactDOM from "react-dom";
import "semantic-ui-css/semantic.min.css";
import { Dropdown } from "semantic-ui-react";
import moment from "moment";
import orderby from "lodash.orderby";

const options = [
  { key: 1, text: "Name", value: "name", icon: "sort" },
  { key: 2, text: "Time", value: "time", icon: "sort" },
  { key: 3, text: "Type", value: "type", icon: "sort" }
];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [],
      original: [],
      sortObject: { field: "", order: "" }
    };
  }

  componentDidMount() {
    let list = [
      {
        name: "namev1",
        time: 1583295463213,
        type: 14
      },
      {
        name: "namea2",
        time: 1582885423296,
        type: 15
      },
      {
        name: "namea3",
        time: 1581295463213,
        type: 16
      }
    ];
    this.setState({ list, original: list });
  }

  handleSearch = e => {
    let searchInput = e.target.value;
    let filteredData = this.state.original.filter(value => {
      return (
        value.name.toLowerCase().includes(searchInput.toLowerCase()) ||
        value.type.toString().includes(searchInput.toString())
      );
    });
    this.setState({ list: filteredData });
  };

  formSortObject = fieldName => {
    let { sortObject } = this.state;
    if (!sortObject.field || sortObject.field !== fieldName) {
      Object.assign(sortObject, {
        field: fieldName,
        order: "asc"
      });
      return sortObject;
    } else if (sortObject.field === fieldName) {
      Object.assign(sortObject, {
        ...sortObject,
        order: sortObject.order === "desc" ? "asc" : "desc"
      });
      return sortObject;
    }
  };

  handleSort = (e, data) => {
    let dropdDownValue = data.value;
    let currentField = this.formSortObject(dropdDownValue);
    let result = orderby(
      this.state.list,
      currentField.field,
      currentField.order
    );
    this.setState({ list: result });
  };

  render() {
    return (
      <>
        Search: <input type="text" onChange={this.handleSearch} />
        <Dropdown text="Sort By" options={options} onChange={this.handleSort} />
        <h1>List</h1>
        <table>
          <tbody>
            {this.state.list.map((item, index) => (
              <tr key={index}>
                <td>
                  <p>{index + 1}</p>
                </td>
                <td>
                  <p>{item.name}</p>
                </td>
                <td>
                  <p>{moment().diff(item.time, "days")}</p>
                </td>
                <td>
                  <p>{item.type}</p>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </>
    );
  }
}

1 Answer 1

2

Your code isnt's working as you spected because you are calling the handleSort function only when the value of the select change (see the onChange of your <Dropdown />).

What you need is the function executed when an option is clicked.

I searched for the documentation of the library you are using and I came to the conclusion that what you need is this.

    <Dropdown text='Sort By'>
        <Dropdown.Menu>
          {options.map(item=>
            <Dropdown.Item text={item.text} value={item.value} icon={item.icon} key={item.key} onClick={this.handleSort}/>
          )}
        </Dropdown.Menu>
    </Dropdown>

I tried it in your codesandbox and it works perfectly!

I hope it helps!

2
  • Thanks much! It helped. Also how could I set the indicator inside the drop-down so that it shows on what order the current filed is sorted?
    – user13349816
    Commented Jul 10, 2020 at 20:29
  • Changing the value of icon when its clicked. react.semantic-ui.com/elements/icon Commented Jul 10, 2020 at 20:41