You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现可按所有表头排序的用户表格问题求助

多表头排序解决方案

现有问题分析

  1. 排序函数硬编码了name字段,无法根据点击的表头动态切换排序目标
  2. 条件判断if (order === "" || "asc")逻辑错误,"asc"为真值会导致永远进入第一个分支
  3. 未记录当前排序字段,无法区分是切换同一字段的排序顺序还是切换到新字段排序

修改步骤及代码

1. 在Home组件添加排序字段状态

添加sortKey状态跟踪当前排序的字段,初始值设为name:

const [sortKey, setSortKey] = useState("name");

2. 重构sortData函数,支持动态字段排序

修改排序逻辑,接收点击的字段名,处理不同类型字段的排序规则(字符串用localeCompare,日期用Date对象比较):

const sortData = (key) => {
  // 点击当前排序字段则切换顺序,点击新字段默认升序
  const newOrder = sortKey === key ? (order === "asc" ? "dsc" : "asc") : "asc";
  setSortKey(key);
  setOrder(newOrder);

  let sortedArr = [...newUserArr].sort((a, b) => {
    // 日期字段特殊处理,用原始值转Date比较
    if (key === "birthday") {
      const dateA = new Date(a.birthday);
      const dateB = new Date(b.birthday);
      return newOrder === "asc" ? dateA - dateB : dateB - dateA;
    }
    // 字符串字段按localeCompare排序
    return newOrder === "asc" 
      ? a[key].localeCompare(b[key]) 
      : b[key].localeCompare(a[key]);
  });

  setNewUserArr(sortedArr);
  setOrdIcon(newOrder === "asc" ? arrowUp : arrowDown);
};

3. 修改Table组件,传递点击的表头字段

修改th的点击事件,传递当前表头对应的字段名(与数据对象的key匹配):

{headerData.map((headerTable) => {
  const key = headerTable.toLowerCase();
  return (
    <th 
      onClick={() => sortData(key)} 
      id={"header-" + key}
      key={key}
    >
      {headerTable} <img src={ordIcon} id="arrow-img" alt="排序箭头" />
    </th>
  );
})}

4. 完整修改后代码

Home组件关键部分
import { useState } from "react";
import Table from "./Table";
import arrowUp from "./path/to/arrow-up.png";
import arrowDown from "./path/to/arrow-down.png";

function Home() {
  const headerUser = ["Name", "Email", "Occupation", "Birthday"];
  const [newUserArr, setNewUserArr] = useState([
    { name: "Alice", email: "alice@example.com", occupation: "Engineer", birthday: "1990-01-01" },
    { name: "Bob", email: "bob@example.com", occupation: "Designer", birthday: "1985-05-15" }
  ]);
  const [order, setOrder] = useState("asc");
  const [ordIcon, setOrdIcon] = useState(arrowUp);
  const [sortKey, setSortKey] = useState("name");

  const sortData = (key) => {
    const newOrder = sortKey === key ? (order === "asc" ? "dsc" : "asc") : "asc";
    setSortKey(key);
    setOrder(newOrder);

    let sortedArr = [...newUserArr].sort((a, b) => {
      if (key === "birthday") {
        const dateA = new Date(a.birthday);
        const dateB = new Date(b.birthday);
        return newOrder === "asc" ? dateA - dateB : dateB - dateA;
      }
      return newOrder === "asc" 
        ? a[key].localeCompare(b[key]) 
        : b[key].localeCompare(a[key]);
    });

    setNewUserArr(sortedArr);
    setOrdIcon(newOrder === "asc" ? arrowUp : arrowDown);
  };

  return (
    <div>
      <Table 
        headerData={headerUser} 
        bodyData={newUserArr} 
        sortData={sortData} 
        ordIcon={ordIcon} 
      />
    </div>
  );
}

export default Home;
Table组件修改后
import { formatDate } from "../../utils/formatDate";
import "./table.css";

function Table(props) {
  const { headerData, bodyData, sortData, ordIcon} = props;

  return (
    <div className="user-data">
      <table className="user-table">
        <thead>
          <tr className="data-th">
            {headerData.map((headerTable) => {
              const key = headerTable.toLowerCase();
              return (
                <th 
                  onClick={() => sortData(key)} 
                  id={"header-" + key}
                  key={key}
                >
                  {headerTable} <img src={ordIcon} id="arrow-img" alt="排序箭头" />
                </th>
              );
            })}
          </tr>
        </thead>
        <tbody>
          {bodyData.map((item, index) => (
            <tr className="data-tr" key={index}>
              <td>{item.name}</td>
              <td>{item.email}</td>
              <td>{item.occupation}</td>
              <td>{formatDate(item.birthday)}</td>               
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default Table;

额外说明

  • 给列表项添加key属性避免React警告
  • 日期排序使用原始的ISO格式字符串转Date对象比较,确保排序准确性
  • 点击同一表头切换排序顺序,点击新表头默认按升序排序

内容的提问来源于stack exchange,提问作者Dênis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:57:20