Почему не сортирует массив если в поле приходит number?

Есть такая вот функция сортировки.

 const onSort = (sortField) => {
    const data = [...programs];
    data.sort((a, b) => (a[sortField] - b[sortField] ? 1 : -1));
    setPrograms(data);
  };

И в таблице есть div при клике по которому происходит сортировка массива.

<div
   className="table__col--listener"
   onClick={() => onSort("listener")}
>

Массив:

const mockPrograms = [
  {
    id: 1,
    name: "Программирование на языке Python",
    date: "07.05.2020",
    listener: "Тест К. С.",
    mail: 10,
    status: 1,
  },
  {
    id: 2,
    name: "Малярные и декоративные работы",
    date: "12.06.2020",
    listener: "Тестов К. С.",
    mail: 5,
    status: 2,
  },
];

По date, listener где в значениях string всё в порядке сортирует, а если приходит number как в status то не хочет.


Ответы (2 шт):

Автор решения: Yugofx

Странно, что у вас по строке все правильно сортируется. Наверное, это простая случайность

Выражение

a[sortField] - b[sortField] ? 1 : -1

Даст -1 только в случае, если a[sortField] - b[sortField] = 0; Вероятнее всего, вы хотите получить что-то вроде:

// Из вашего кода не особо понятно, какой порядок сортировки вам нужен
data.sort((a, b) => a[sortField] - b[sortField]); // status: 1 будет идти раньше чем status: 2
data.sort((a, b) => b[sortField] - a[sortField]); // наоборот

А если есть необходимость сравнивать строки, то обязательно приводите к одному кейсингу. Строки посимвольно конвертируются в числовые значения по таблице ASCII, поэтому слова, начинающиеся с большой буквы всегда будут идти раньше слов с маленькой:

data.sort((a, b) => {
    if (typeof a[sortField] === 'string') {
        return a[sortField].toLowerCase() < b[sortField].toLowerCase() ? -1 : 1;
    }

    return b[sortField] - a[sortField];
});

Если необходимо менять направление сортировки, объявите переменную вне функции сортировки.

let direction = 1;

В самой функции проверяйте поле сортировки. Если пришло то же поле, то меняйте значение сортировки на -1.

let sortField;

function onSort(criteria) {
    if (sortField === criteria) {
        direction *= -1;
    } else {
        direction = 1;
    }
    sortField = criteria;

    ...
    data.sort((a, b) => (a[sortField] - b[sortField]) * direction);
}
→ Ссылка
Автор решения: IvaMuxa

const onSort = (sortField) => {
  const data = mockPrograms;
  data.sort((a, b) => ((a[sortField] - b[sortField]) >= 0 ? 1 : -1));
  setPrograms(data);
};


const mockPrograms = [{
    id: 1,
    name: "Программирование на языке Python",
    date: "07.05.2020",
    listener: "Тест К. С.",
    mail: 10,
    status: 1,
  },
  {
    id: 2,
    name: "Малярные и декоративные работы",
    date: "12.06.2020",
    listener: "Тестов К. С.",
    mail: 5,
    status: 2,
  },
];

function setPrograms(data) {
  for (let i = 0; i < data.length; i++) {
    document.getElementById(`tr${i}`).innerHTML = `<td>${data[i].id}</td><td>${data[i].name}</td><td>${data[i].date}</td><td>${data[i].listener}</td><td>${data[i].mail}</td><td>${data[i].status}</td>`;
  }
}

setPrograms(mockPrograms);
td{border: 1px solid black;
<table>
  <tr>
    <td class="table__col--listener" onClick="onSort('id')">id</td>
    <td class="table__col--listener" onClick="onSort('name')">name</td>
    <td class="table__col--listener" onClick="onSort('date')">date</td>
    <td class="table__col--listener" onClick="onSort('listener')">listener</td>
    <td class="table__col--listener" onClick="onSort('mail')">mail</td>
    <td class="table__col--listener" onClick="onSort('status')">status</td>
  </tr>
  <tr id="tr0"></tr>
  <tr id="tr1"></tr>
</table>

→ Ссылка