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

React-Pagination实现表格默认按序号排序问题求助

问题描述

我有一个表格,需要让它默认按第一列的数字1、2、3……排序,当前使用React-Pagination组件。我四处查找资料,但找到的都是点击按钮触发排序的方案,希望有人能帮助我或指明解决方向。

以下是我的代码:

import axios from "axios";
import React, { useState, useEffect } from "react";
import Pagination from "https://cdn.skypack.dev/rc-pagination@3.1.15";


const News = () => {
  const [playerName, setPlayerName] = useState([]);
  const [playerRank, setPlayerRank] = useState([]);
  const [player, setPlayer] = useState([]);
  const [perPage, setPerPage] = useState(10);
  const [size, setSize] = useState(perPage);
  const [current, setCurrent] = useState(1);
  const [players, setPlayers] = useState();

  const fetchData = () => {
    const playerAPI = 'http://localhost:3008/api/players';
    const playerRank = 'http://localhost:3008/api/highscore/players';

    const getINFOPlayer = axios.get(playerAPI)
    const getPlayerRank = axios.get(playerRank)
    axios.all([getINFOPlayer, getPlayerRank]).then(
      axios.spread((...allData) => {
        const allDataPlayer = allData[0].data.players
        const getINFOPlayerRank = allData[1].data.players
        const newPlayer = allDataPlayer.map(name => {
          const pr = getINFOPlayerRank.find(rank => name.id === rank.id)


          return {
            id: name.id,
            name: name.name,
            status: name.status,
            position: pr?.position,
            score: pr?.score
          }

          // or simply do the following if the keys doesn't matter: return {...name, ...pr}
        })

        setPlayerName(allDataPlayer)
        setPlayerRank(getINFOPlayerRank)

        console.log(newPlayer)
        setPlayer(newPlayer)
      })
    )
  }
  useEffect(() => {
    fetchData()
  }, [])

  const PerPageChange = (value) => {
    setSize(value);
    const newPerPage = Math.ceil(players.length / value);
    if (current > newPerPage) {
      setCurrent(newPerPage);
    }
  }

  const getData = (current, pageSize) => {
    // Normally you should get the data from the server
    return player?.slice((current - 1) * pageSize, current * pageSize);
  };

  const sortData = getData && player?.sort((a, b) => a.position > b.position ? 1 : -1)

  const PaginationChange = (page, pageSize) => {
    setCurrent(page);
    setSize(pageSize)
  }

  const PrevNextArrow = (current, type, originalElement) => {
    if (type === 'prev') {
      return <button><i className="fa fa-angle-double-left"></i></button>;
    }
    if (type === 'next') {
      return <button><i className="fa fa-angle-double-right"></i></button>;
    }
    return originalElement;
  }


  return (
    <>
      <div className="container-fluid mt-5 mb-5">
        <div className="row justify-content-center">
          <div className="col-md-10">
            <div className="card">
              <div className="card-body p-0">

                <div className="table-filter-info">

                  <Pagination
                    className="pagination-data"
                    showTotal={(total, range) => `Showing ${range[0]}-${range[1]} of ${total}`}
                    onChange={PaginationChange}
                    total={player.length}
                    current={current}
                    pageSize={size}
                    showSizeChanger={false}
                    itemRender={PrevNextArrow}
                    onShowSizeChange={PerPageChange}
                  />
                </div>
                <div className="table-responsive">
                  <table className="table table-text-small mb-0">
                    <thead className="thead-primary table-sorting">
                      <tr>
                        <th>#</th>
                        <th>Name</th>
                        <th>Points</th>
                        <th>Alliance</th>
                        <th>Status</th>
                      </tr>
                    </thead>
                    <tbody>
                      {getData(current, size)
                        .map((player) => {
                          return (
                            <tr key={player.name}>
                              <td>{player.position}</td>
                              <td>{player.name}</td>
                              <td>{player.score}</td>
                              <td>{player.alliance}</td>
                              <td>{player.status}</td>
                            </tr>
                          );
                        })}
                    </tbody>
                  </table>
                </div>
                <div className="table-filter-info">

                  <Pagination
                    className="pagination-data"
                    showTotal={(total, range) => `Showing ${range[0]}-${range[1]} of ${total}`}
                    onChange={PaginationChange}
                    total={player.length}
                    current={current}
                    pageSize={size}
                    showSizeChanger={false}
                    itemRender={PrevNextArrow}
                    onShowSizeChange={PerPageChange}
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  )
}


export default News
解决方案

要实现表格默认按第一列(position)数字排序,不需要额外点击触发,只需在数据处理阶段完成排序即可,以下是具体修改步骤:

1. 在数据合并后直接排序

原代码中sortData变量未实际生效,且Array.sort()会原地修改数组,建议在合并完玩家数据后立即排序,再存入状态:

const fetchData = () => {
  const playerAPI = 'http://localhost:3008/api/players';
  const playerRank = 'http://localhost:3008/api/highscore/players';

  const getINFOPlayer = axios.get(playerAPI)
  const getPlayerRank = axios.get(playerRank)
  axios.all([getINFOPlayer, getPlayerRank]).then(
    axios.spread((...allData) => {
      const allDataPlayer = allData[0].data.players
      const getINFOPlayerRank = allData[1].data.players
      const newPlayer = allDataPlayer.map(name => {
        const pr = getINFOPlayerRank.find(rank => name.id === rank.id)
        return {
          id: name.id,
          name: name.name,
          status: name.status,
          position: pr?.position,
          score: pr?.score,
          alliance: name.alliance // 补充原代码缺失的alliance字段
        }
      })

      // 新增排序逻辑:按position升序,处理position不存在的情况
      const sortedPlayers = [...newPlayer].sort((a, b) => {
        if (a.position === undefined) return 1;
        if (b.position === undefined) return -1;
        return a.position - b.position;
      });

      setPlayerName(allDataPlayer)
      setPlayerRank(getINFOPlayerRank)
      setPlayer(sortedPlayers) // 存入排序后的数组
    })
  )
}

2. 移除无效代码

删除原代码中未生效的sortData变量:

// 删掉此行
const sortData = getData && player?.sort((a, b) => a.position > b.position ? 1 : -1)

3. 修正分页数据逻辑

因为状态中的player已经是排序好的数组,getData可以直接使用原逻辑,分页展示的内容会自动按顺序排列。

另外注意:原代码表格的Alliance列用到了player.alliance,但之前合并数据时未赋值,需要在返回的对象中补充alliance: name.alliance,否则该列会显示undefined。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:45:31