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

ReactJS分页表格全局连续倒序编号实现问题求助

问题描述

需要在ReactJS中实现带分页功能的表格,满足以下要求:

  • 表格编号为全局数据的连续倒序,切换分页时编号不会重新开始计数。例如:

    第一页显示:

    10 XXX
    9 XXX
    8 XXX
    7 XXX
    6 XXX
    

    第二页显示:

    5 XXX
    4 XXX
    3 XXX
    2 XXX
    1 XXX
    
  • 管理员发布的"Notice"帖子需始终显示在所有普通帖子的最上方。

当前实现切换分页时编号无法连续,错误显示为:

10 XXX
9 XXX
8 XXX
7 XXX
6 XXX
5 XXX
现有代码
const rawData = [
  {
    writer: "Admin",
    post_admin: true,
    new_post: false,
    title: "Test",
    slug: "test",
    code: "230109000001",
    created_at: "2023-01-09 15:56:59",
    view: 3,
    share: 1,
    jumlah_like: 0,
    jumlah_komen: 4,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "pink",
    slug: "pink",
    code: "230120000112",
    created_at: "2023-01-20 13:19:23",
    view: 2,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "weather 3",
    slug: "weather-3",
    code: "230120000111",
    created_at: "2023-01-20 13:16:32",
    view: 1,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "weather 2",
    slug: "weather-2",
    code: "230120000110",
    created_at: "2023-01-20 13:15:10",
    view: 2,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "weather",
    slug: "weather",
    code: "230120000109",
    created_at: "2023-01-20 13:13:47",
    view: 1,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Putri Seprina",
    post_admin: false,
    new_post: false,
    title: "postingan 19 saya",
    slug: "postingan-19-saya",
    code: "230120000102",
    created_at: "2023-01-20 10:08:46",
    view: 4,
    share: 1,
    jumlah_like: 1,
    jumlah_komen: 5,
  },
  {
    writer: "Putri Seprina",
    post_admin: false,
    new_post: false,
    title: "postingan 1 saya",
    slug: "postingan-1-saya",
    code: "230120000056",
    created_at: "2023-01-20 10:00:38",
    view: 1,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "57",
    slug: "57",
    code: "230120000045",
    created_at: "2023-01-20 09:58:37",
    view: 0,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "58",
    slug: "58",
    code: "230120000044",
    created_at: "2023-01-20 09:58:22",
    view: 0,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
  {
    writer: "Dafni Lanahtadya",
    post_admin: false,
    new_post: false,
    title: "59",
    slug: "59",
    code: "230120000043",
    created_at: "2023-01-20 09:58:14",
    view: 0,
    share: 0,
    jumlah_like: 0,
    jumlah_komen: 0,
  },
];

function Index() {
  const [listSubPost, setListSubPost] = useState(rawData);
  const [countPage, setCountPage] = useState(0);
  const [currentPage, setCurrentPage] = useState(1);
  const [perPage, setPerPage] = useState(5);
  const [dataCount, setDataCount] = useState(31);
  const [dataAdminCount, setDataAdminCount] = useState(0);
  const [initialPage, setInitialPage] = useState(1);

  const setPage = (array, page_size, page_number) => {
    // human-readable page numbers usually start with 1, so we reduce 1 in the first argument
    setListSubPost(
      array.slice((page_number - 1) * page_size, page_number * page_size)
    );
  };

  let _indexUser = 0;
  let _countAll = dataCount - dataAdminCount;

  return (
    <>
      <div>
        <table
          aria-label="Example static collection table"
          style={{
            height: "auto",
            minWidth: "100%",
            overflowX: "auto",
          }}
        >
          <thead>
            <td>Number</td>
            <td>TITLE</td>
            <td>WRITER</td>
            <td>DATE</td>
            <td>LIKES</td>
            <td>VIEWS</td>
          </thead>
          <tbody>
            {listSubPost.map((item, index) => {
              if (!item?.post_admin) {
                _indexUser = _indexUser + 1;
              }
              return (
                <tr key={index}>
                  <td>
                    {item?.post_admin
                      ? "Notice"
                      : _countAll -
                        (_indexUser - 2) -
                        Math.ceil(currentPage / perPage)}
                  </td>
                  <td>{item.title}</td>
                  <td>{item.writer}</td>
                  <td>{item.created_at}</td>
                  <td>{item.jumlah_like}</td>
                  <td>{item.view}</td>
                </tr>
              );
            })}
          </tbody>
        </table>

        <button onClick={() => setPage(rawData, 5, 1)}>page 1</button>
        <button onClick={() => setPage(rawData, 5, 2)}>page 2</button>
      </div>
    </>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
修正方案
const rawData = [
  // 原数据不变,省略...
];

// 预处理数据:管理员帖子固定排最前面
const sortedData = [...rawData].sort((a, b) => {
  if (a.post_admin && !b.post_admin) return -1;
  if (!a.post_admin && b.post_admin) return 1;
  return 0;
});

function Index() {
  const [currentPage, setCurrentPage] = useState(1);
  const perPage = 5; // 每页显示5条

  // 获取当前页的数据
  const getCurrentPageData = () => {
    const startIdx = (currentPage - 1) * perPage;
    return sortedData.slice(startIdx, startIdx + perPage);
  };

  // 统计全局普通帖子总数
  const totalNormalPosts = sortedData.filter(item => !item.post_admin).length;

  return (
    <>
      <div>
        <table
          aria-label="Example static collection table"
          style={{
            height: "auto",
            minWidth: "100%",
            overflowX: "auto",
          }}
        >
          <thead>
            <tr>
              <td>Number</td>
              <td>TITLE</td>
              <td>WRITER</td>
              <td>DATE</td>
              <td>LIKES</td>
              <td>VIEWS</td>
            </tr>
          </thead>
          <tbody>
            {getCurrentPageData().map((item, localIdx) => {
              // 计算当前项在全局数据中的索引
              const globalIdx = (currentPage - 1) * perPage + localIdx;

              if (item.post_admin) {
                return (
                  <tr key={item.code}>
                    <td>Notice</td>
                    <td>{item.title}</td>
                    <td>{item.writer}</td>
                    <td>{item.created_at}</td>
                    <td>{item.jumlah_like}</td>
                    <td>{item.view}</td>
                  </tr>
                );
              }

              // 计算当前普通帖在全局中的顺序位置
              const globalNormalIdx = sortedData
                .slice(0, globalIdx + 1)
                .filter(i => !i.post_admin).length;
              // 生成倒序编号
              const serialNum = totalNormalPosts - globalNormalIdx + 1;

              return (
                <tr key={item.code}>
                  <td>{serialNum}</td>
                  <td>{item.title}</td>
                  <td>{item.writer}</td>
                  <td>{item.created_at}</td>
                  <td>{item.jumlah_like}</td>
                  <td>{item.view}</td>
                </tr>
              );
            })}
          </tbody>
        </table>

        <button 
          onClick={() => setCurrentPage(1)}
          disabled={currentPage === 1}
        >
          第1页
        </button>
        <button 
          onClick={() => setCurrentPage(2)}
          disabled={currentPage === 2}
        >
          第2页
        </button>
      </div>
    </>
  );
}
关键修正点
  1. 数据预处理:提前将管理员帖子排序到全局数据最前面,确保分页时管理员帖始终在当前页顶部。
  2. 全局索引计算:通过当前页码+本地索引,获取项在全局数据中的位置,避免分页丢失全局顺序信息。
  3. 倒序编号逻辑:基于全局普通帖的顺序,用总普通帖数减去当前帖的全局位置,生成连续倒序编号。
  4. key优化:使用数据中唯一的code作为列表项key,避免index作为key导致的渲染异常。
  5. HTML规范修正:thead中的td用tr包裹,符合表格结构标准。

内容的提问来源于stack exchange,提问作者AhmadR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:55:24