#javascript #arrays #reactjs #object
Вопрос:
ОБНОВЛЕНИЕ: Вот ссылка на codesandbox: https://codesandbox.io/s/15tn7?file=/client/src/App.js Однако есть проблема в том, что приложение не отображается в браузере codesandbox. Может кто-нибудь помочь мне понять, в чем проблема с этим? Я не очень хорошо знаком с codesandbox.
У меня есть компонент, который в основном представляет собой таблицу списка сотрудников. Таблица сотрудники составляется из массива объектов, называемых сотрудниками, в котором каждый объект имеет ключ фамилии (среди прочих). Я хочу иметь возможность нажать, чтобы перейти на вкладку «Имя» таблицы, чтобы расположить сотрудников в алфавитном порядке по фамилии. Я создал функцию для этого:
const nameSort = () => {
let employeeCopy = [];
employeeCopy = employees;
employeeCopy.sort((a, b) => {
if (a.last_name.toLowerCase() < b.last_name.toLowerCase()) return -1;
if (a.last_name.toLowerCase() > b.last_name.toLowerCase()) return 1;
return 0;
});
setEmployees(employeeCopy);
console.log("name sort ran");
console.log("employees: ", employees);
};
Функция работает просто отлично. Когда я утешаю.войдите в массив сотрудников, он выходит точно так, как я хочу, в алфавитном порядке по ключу фамилии. Однако компонент никогда не обновляется на основе этого вновь отсортированного массива. Может ли кто-нибудь помочь мне понять, как исправить эту проблему?
Вот как отображается таблица:
<table className="et-tbl">
<tr>
<th onClick={nameSort}>Name</th>
<th onClick={emailSort}>Email</th>
<th>Phone</th>
<th></th>
</tr>
{employees.map((employee) => (
<tr key={employee.id}>
<td>
<div
className="et-tbl-name-cell"
onClick={() => renderProfile(employee, employee.id)}
>
{employee.photo ? (
<img
src={employee.photo}
alt={`${employee.first_name} ${employee.last_name}`}
/>
) : (
<div></div>
)}
{employee.last_name}, {employee.first_name}
</div>
</td>
<td>{employee.email}</td>
<td>{employee.phone}</td>
<td className="et-tbl-icon-cell">
<div
className="et-tbl-icon"
onClick={() => renderProfile(employee, employee.id)}
>
<AiFillProfile />
</div>
<div
className="et-tbl-icon"
onClick={() => editEmployee(employee)}
>
<MdModeEdit />
</div>
<div className="et-tbl-icon">
<VscChromeClose />
</div>
</td>
</tr>
))}
</table>
Комментарии:
1. пожалуйста, не могли бы вы приложить полный код ? codesandbox может быть хорошим вариантом
2. Покажите нам полный код.
3. Попробуй
setEmployees([...employeeCopy])
4. @Codenewbie Вот ссылка на codesandbox: codesandbox.io/s/15tn7?file=/client/src/App.js
Ответ №1:
Я не смог протестировать свой код (так что я мог ошибаться), но эта строка в вашем коде:
employeeCopy = employees;
не создает копию сотрудников, поскольку сотрудники-это сложный тип (т. е. массив).
Кроме того, Array.prototype.sort
сортирует массив на месте (вместо создания копии).
Эти два пункта выше являются проблемой в данном контексте, поскольку это означает, что ссылка на employees
никогда не меняется (поскольку массив мутирует на месте). Способ, которым React обнаруживает изменения состояния в сложных типах (объектах, массивах и т. Д.), Заключается в поверхностной проверке того, изменилась ли их ссылка.
Непроверено, но я думаю, что функцию nameSort
можно переписать что-то вроде:
const nameSort = () => {
setEmployees((prev) => {
return [...prev].sort((a, b) => {
if (a.last_name.toLowerCase() < b.last_name.toLowerCase()) return -1;
if (a.last_name.toLowerCase() > b.last_name.toLowerCase()) return 1;
return 0;
});
});
};
Основной вывод состоит в том , чтобы использовать синтаксис распространения ...
для создания неглубокой копии (хотя копия также могла быть получена с помощью методов массива: slice
или map
, например).
Функция emailSort
может быть переписана аналогичным образом:
const emailSort = () => {
setEmployees((prev) => {
return [...prev].sort((a, b) => {
if (a.email.toLowerCase() < b.email.toLowerCase()) return -1;
if (a.email.toLowerCase() > b.email.toLowerCase()) return 1;
return 0;
});
});
};
Примечание: если это настоящие ключи API/учетные данные в коде, которым вы поделились, вы можете войти в службы (Firebase и т. Д.), отозвать эти учетные данные и создать новые, другие. Просто для того, чтобы никакие посторонние люди не могли (неправильно)использовать эти услуги, выдавая себя за вас.