[英]sorting array of objects and updating state
更新:这里是代码框链接: https://codesandbox.io/s/15tn7?file=/client/src/App.js虽然存在一个问题,即应用程序没有在代码框浏览器中呈现。 有人可以帮我弄清楚这有什么问题吗? 我对codeandbox不是很熟悉。
我有一个组件,它基本上是一个员工列表表。 employees 表从一个名为 employees 的对象数组中提取,其中每个 object 都有一个姓氏键(等等)。 我希望能够单击以单击表的“名称”选项卡,以按姓氏的字母顺序排列员工。 我创建了一个 function 来执行此操作:
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);
};
function 运行良好。 当我 console.log 员工数组时,它完全按照我想要的按姓氏键的字母顺序显示。 但是,组件永远不会根据这个新排序的数组进行更新。 有人可以帮我弄清楚如何解决这个问题吗?
这就是表格的呈现方式:
<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>
我无法测试我的代码(所以我可能是错的),但是代码中的这一行:
employeeCopy = employees;
不会复制员工,因为员工是复杂类型(即数组)。
此外, Array.prototype.sort
对数组进行就地排序(而不是制作副本)。
以上两点在这种情况下是一个问题,因为这意味着employees
的参考永远不会改变(因为数组是原地变异的)。 React 在复杂类型(对象、arrays 等)中检测 state 变化的方式是通过浅层检查它们的引用是否发生变化。
未经测试,但我认为 function 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
)。
Function 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 等),撤销这些凭据并重新生成新的不同的凭据。 只是为了没有未经授权的人可以(误)假装是您来使用这些服务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.