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> </> ); }
关键修正点
- 数据预处理:提前将管理员帖子排序到全局数据最前面,确保分页时管理员帖始终在当前页顶部。
- 全局索引计算:通过当前页码+本地索引,获取项在全局数据中的位置,避免分页丢失全局顺序信息。
- 倒序编号逻辑:基于全局普通帖的顺序,用总普通帖数减去当前帖的全局位置,生成连续倒序编号。
- key优化:使用数据中唯一的
code作为列表项key,避免index作为key导致的渲染异常。 - HTML规范修正:thead中的td用tr包裹,符合表格结构标准。
内容的提问来源于stack exchange,提问作者AhmadR
相关产品推荐
相关产品推荐

