【问题标题】:sorting array of objects and updating state对对象数组进行排序并更新状态
【发布时间】:2021-06-05 17:10:52
【问题描述】:

更新:这里是代码框链接:https://codesandbox.io/s/15tn7?file=/client/src/App.js 但存在一个问题,即应用程序未在代码框浏览器中呈现。有人可以帮我弄清楚这有什么问题吗?我对codeandbox不是很熟悉。

我有一个组件,它基本上是一个员工列表表。 employees 表从一个名为 employees 的对象数组中提取,其中每个对象都有一个姓氏键(等等)。我希望能够单击以单击表的“名称”选项卡,以按姓氏的字母顺序排列员工。我创建了一个函数来执行此操作:

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);
};

该功能运行良好。当我 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>

【问题讨论】:

标签: javascript arrays reactjs object


【解决方案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;
    });
  });
};

主要内容是使用扩展语法... 进行浅拷贝(尽管也可以使用数组方法实现拷贝:例如slicemap)。


函数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 等),撤销这些凭据并重新生成新的不同的凭据。以免未经授权的人冒充您(误用)这些服务。

【讨论】:

    猜你喜欢
    • 2016-03-04
    • 1970-01-01
    • 2020-07-01
    • 2020-08-07
    • 2011-08-18
    相关资源
    最近更新 更多