1

I'm trying to handle a sort function that toggles between dsc and asc. It also needs to handle a certain table column name which is referred to as "header". The expected outcome is to sort either "days" or "station" and have it toggle separately between dsc and asc.

handleClick={(val: any, header: string) =>
  val((val: any) => {
    const result = [...val].sort((a: any, b: any) => {
      return sortOrder === 'asc'
        ? header === 'Station'
          ? b.station - a.station
          : b.days - a.days
        : header === 'Station'
          ? a.station - b.station
          : a.days - b.days;
    });
    setSortOrder(sortOrder === 'asc' ? 'dsc' : 'asc');
    return result;
  })
}

This is my current function station filters properly but "Days Since Last Event" doesn't seem to work.

This is the handleClick on the child function

onClick={() => props.handleClick(setFilteredData, header)}

This is the sample of the data

[
  {
    days: 23,
    station: "Braidwood",
  },
  {
    days: 18,
    station: "Byron",
  },
  {
    days: 28,
    station: "Byron",
  },
  {
    days: 32,
    station: "Calvert Cliffs",
  },
  {
    days: 20,
    station: "Dresden",
  },
  {
    days: 320,
    station: "Dresden",
  },
];
4
  • Can you please explain what you want to have happen? I'm guessing that you want it to sort by one property or the other, or first one, then the other...but it's not really clear. Commented Aug 5, 2021 at 19:50
  • the problem starts where you are changing sortOrder state, however, you should know that setState has some "timeOut" and it doesn't update immediatley. developpaper.com/on-the-data-delay-in-this-setstate Commented Aug 5, 2021 at 19:53
  • @MattMorgan it to sort by one property or the other is correct Commented Aug 5, 2021 at 19:54
  • @yairmea Yes I think you're right I think in need to store which asc order for which property in the state Commented Aug 5, 2021 at 20:34

1 Answer 1

1

Issues

As-written, your handler sorts a copy of the filteredData and then toggles the sorting order. This means the actual order is always inverted from the current sortOrder state.

If I had to guess, I would say the onClick handler is supposed to toggle the sorting order, and then you want the filteredData state to be resorted.

Solution

The onClick handler should toggle the state, and the resorting can be done in an useEffect hook with a dependency on the sortOrder and header state.

React.useEffect(() => {
  setFilteredData(data => data.slice().sort((a: any, b: any) => {
    return sortOrder === 'asc'
      ? header === 'Station'
        ? b.station - a.station
        : b.days - a.days
      : header === 'Station'
        ? a.station - b.station
        : a.days - b.days;
  }));
}, [header, sortOrder]);

const toggleSortOrder = (header: string) => () => {
  setSortOrder(sortOrder === 'asc' ? 'dsc' : 'asc');
  setSortHeader(header);
};

...

handleClick={toggleSortOrder(header)}

Additionally, since the ascending/descending functionality is basically the same, I'd suggest converting the sort comparator into a higher order function that swaps the inputs and return a simpler comparator function.

const customSort = (sortOrder = 'asc', header = 'Station') => {
  const comparator = (a: any, b: any) => header === 'Station'
    ? b.station - a.station
    : b.days - a.days;
  return sortOrder === 'asc' ? comparator : (a, b) => comparator(b, a);
}

React.useEffect(() => {
  setFilteredData(data => data.slice().sort(customSort(sortOrder, header)));
}, [header, sortOrder]);
Sign up to request clarification or add additional context in comments.

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.