Why my table is not reflecting the sort that I made asap? I need to select multiple times (on my filter by select option) for it to render in tbody

Viewed 41

My goal is to have a table that I can sort by location or activationDate using <select>. Now my sorting is now working but I need to select options(location or activationDate) multiple times for it to reflect in the table. What I need to do to make my sorting reflect asap after I select (eg. sort by location)

my sample obect:

[
  {
    fullName: "honer Baron", 
    location: "A building", 
    activationDate: "2022-07-08 09:30:34"
  },
  {
    fullName: "jett valo", 
    location: "B building",
    activationDate: "2022-07-07 10:30:34"
  }
]
const AgentSalesModal = ({ obectsToputInTable, show, hide }) => {
  const [sortBy , setSortBy] = useState("");
  const tableRow = [];

  useEffect(() => {
    setTableRow();
  }, [sortBy ]);

  const setTableRow = () => {
    if (sortBy == "location") {
      return obectsToputInTable
        .sort((a, b) => {
          console.log(filterBy);
          return a.location - b.location;
        })
        .map((item, key) => (
          <tr key={key}>
            <td>{item.location}</td>
            <td>
              {item.fullName}
            </td>
            <td>{item.activationDate}</td>
          </tr>
        ));
    } else {
      return obectsToputInTable
        .sort((a, b) => {
          var dateA = new Date(a.date).getTime();
          var dateB = new Date(b.date).getTime();
          return dateA > dateB ? 1 : -1;
        })
        .map((item, key) => (
          <tr key={key}>
            <td>{item.location}</td>
            <td>{item.subscriberId}</td>
            <td>
              {item.fullName}
            </td>
            <td>{item.activationDate}</td>
          </tr>
        ));
    }
  };

  const hideModal = () => {
    hide();
    setSortBy("");
  };

  return (
    <React.Fragment>
      <Modal
        show={show}
        onHide={hideModal}
        size="lg"
        aria-labelledby="contained-modal-title-vcenter"
        centered>
        <Modal.Header>
          <Modal.Title id="contained-modal-title-vcenter">
            Sales Commission
          </Modal.Title>
        </Modal.Header>
        <Modal.Body className="dateModal text-center">
          <div className="overflow">
            <form>
              <select
                className="form-select mb-4"
                onChange={(e) => setSortBy(e.target.value)}>
                <option value="" disabled defaultValue hidden>
                  Select Value to sort by
                </option>
                <option value="location">Sort by Location</option>
                <option value="activationDate">Sort by Activation Date</option>
              </select>
            </form>

            <table className="table">
              <thead>
                <tr>
                  <th>Location</th>
                  <th>Subscriber Fullname</th>
                  <th>Activation Date</th>
                </tr>
              </thead>
              <tbody>{setTableRow()}</tbody>
            </table>
          </div>
        </Modal.Body>
        <Modal.Footer>
          <Button
            onClick={() => {
              hide();
              setSortBy("");
            }}>
            Close
          </Button>
        </Modal.Footer>
      </Modal>
    </React.Fragment>
  );
};```
1 Answers

I would use another state to render the result of setTableRow() eg., rows.

const [rows, setRows] = useState([]);

And set the state in the useEffect with the sortBy dependency.

useEffect(() => {
  const tableRows = setTableRow();
  setRows(tableRows);
}, [sortBy]);

In your render method:

<tbody>{rows}</tbody>

UPDATE

Ideally in this scenario we want to compare using === instead of == but if you introduce antoher filter option a switch will work better, lets try this instead:

const setTableRow = () => {
    // Check the value of sortBy here instead
    console.log('sortBy', sortBy);

    switch(sortBy) {
      case "location":
        return obectsToputInTable
        .sort((a, b) => {
          return a.location - b.location;
        })
        .map((item, key) => (
          <tr key={key}>
            <td>{item.location}</td>
            <td>
              {item.fullName}
            </td>
            <td>{item.activationDate}</td>
          </tr>
        ));
      case "activationDate":
        return obectsToputInTable
        .sort((a, b) => {
          var dateA = new Date(a.date).getTime();
          var dateB = new Date(b.date).getTime();
          return dateA > dateB ? 1 : -1;
        })
        .map((item, key) => (
          <tr key={key}>
            <td>{item.location}</td>
            <td>{item.subscriberId}</td>
            <td>
              {item.fullName}
            </td>
            <td>{item.activationDate}</td>
          </tr>
        ));
      default:
        return obectsToputInTable
        .map((item, key) => (
          <tr key={key}>
            <td>{item.location}</td>
            <td>{item.subscriberId}</td>
            <td>
              {item.fullName}
            </td>
            <td>{item.activationDate}</td>
          </tr>
        ));
    }
  };

Side note: The key in the map(item, key) function simply returns an index value, you may be better off using item.subscriberId instead but I don't see that value in the sample json.

Related