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

如何在React类组件中结合Axios实现表格分页功能

解决方案

本次实现的是前端分页方案,适配你当前一次性拉取全量用户数据的场景,修改内容如下:

  • state新增分页核心参数:当前页码currentPage、每页展示条数pageSize
  • 搜索关键词变更时自动重置页码到第一页,避免出现页码超出总页数的空白情况
  • 对过滤后的用户数据做切片渲染,仅展示当前页对应数据
  • 新增分页控制器UI,完全适配Tailwind CSS样式

完整修改后代码

import React, { Component } from "react";
import axios from "axios";
import Search from "../components/Search";
import Users from "../Users";

class UsersManagement extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [],
      search: "",
      sort: ["Oldest", "Newest"],
      currentSort: "Oldest", // 补充排序状态管理,修复原代码排序功能依赖props的问题
      currentPage: 1, // 新增:当前页码
      pageSize: 10, // 新增:每页展示条数,可自行调整
    };
  }

  componentDidMount() {
    axios
      .get("http://localhost/crud-user/php/users.php")
      .then((res) => {
        this.setState({ users: res.data });
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  displayUsers() {
    // 1. 先过滤搜索结果
    let filteredUsers = this.state.users.filter(
      (user) =>
        user.first_name
          .toLowerCase()
          .includes(this.state.search.toLowerCase()) ||
        user.last_name.toLowerCase().includes(this.state.search.toLowerCase())
    );

    // 2. 处理排序逻辑(补充原缺失的排序功能)
    filteredUsers = filteredUsers.sort((a, b) => {
      if (this.state.currentSort === "Newest") {
        return new Date(b.created_at) - new Date(a.created_at);
      }
      return new Date(a.created_at) - new Date(b.created_at);
    });

    // 3. 按当前页切片数据
    const paginatedUsers = filteredUsers.slice(
      (this.state.currentPage - 1) * this.state.pageSize,
      this.state.currentPage * this.state.pageSize
    );

    return paginatedUsers.map(function (object, index) {
      return <Users obj={object} key={index} />;
    });
  }

  // 新增:获取过滤后总数据条数、总页数
  getPaginationInfo() {
    const filteredUsers = this.state.users.filter(
      (user) =>
        user.first_name
          .toLowerCase()
          .includes(this.state.search.toLowerCase()) ||
        user.last_name.toLowerCase().includes(this.state.search.toLowerCase())
    );
    return {
      total: filteredUsers.length,
      totalPages: Math.ceil(filteredUsers.length / this.state.pageSize),
    };
  }

  render() {
    const { total, totalPages } = this.getPaginationInfo();
    return (
      <div className="flex flex-col">
        <div className="w-full text-center leading-10 mt-10">
          <span className="text-black not-italic font-extrabold text-5xl">
            USER MANAGEMENT
          </span>
        </div>
        <div className="md:px-32 w-screen mt-10">
          <div className="flex overflow-hidden w-10/12 mx-auto">
            <div className="w-full mb-5">
              <Search
                onSearch={(e) => this.setState({ search: e.target.value, currentPage: 1 })}
              />
            </div>
            <div className="w-full mb-5 text-right">
              <select
                name="sort"
                value={this.state.currentSort}
                onChange={(e) => this.setState({ currentSort: e.target.value, currentPage: 1 })}
                className="border-2 border-black rounded-xl h-12 px-5 outline-none cursor-pointer"
              >
                {this.state.sort.map((sort) => (
                  <option className="cursor-pointer" value={sort} key={sort}>
                    {sort}
                  </option>
                ))}
              </select>
            </div>
          </div>
          <div className="overflow-hidden w-10/12 mx-auto">
            <table className="min-w-full bg-white">
              <thead className="bg-white text-black border-b-2 border-gray-500">
                <tr>
                  <th className="w-1/5 text-left py-3 px-4 font-semibold text-lg">
                    User ID
                  </th>
                  <th className="w-1/4 text-left py-3 px-4 font-semibold text-lg">
                    Name
                  </th>
                  <th className="w-1/4 text-left py-3 px-4 font-semibold text-lg">
                    E-mail
                  </th>
                  <th className="text-center py-3 px-4 font-semibold text-lg">
                    Phone Number
                  </th>
                  <th className="text-center py-3 px-4 font-semibold text-lg">
                    Birthdate
                  </th>
                </tr>
              </thead>
              <tbody className="text-black">
                {total > 0 ? (
                  this.displayUsers()
                ) : (
                  <tr>
                    <td colSpan="5" className="py-5 text-center">
                      <p className="text-lg text-red-700 cursor-default">
                        No data available!
                      </p>
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          {/* 新增分页控制器 */}
          {total > 0 && (
            <div className="flex justify-between items-center mt-6 w-10/12 mx-auto">
              <span className="text-gray-700">共 {total} 条数据</span>
              <div className="flex gap-2">
                <button
                  onClick={() => this.setState(prev => ({ currentPage: prev.currentPage - 1 }))}
                  disabled={this.state.currentPage === 1}
                  className="px-4 py-2 border rounded-lg disabled:bg-gray-100 disabled:cursor-not-allowed hover:bg-gray-50 transition-colors"
                >
                  上一页
                </button>
                <span className="px-4 py-2 flex items-center">
                  {this.state.currentPage} / {totalPages}
                </span>
                <button
                  onClick={() => this.setState(prev => ({ currentPage: prev.currentPage + 1 }))}
                  disabled={this.state.currentPage === totalPages}
                  className="px-4 py-2 border rounded-lg disabled:bg-gray-100 disabled:cursor-not-allowed hover:bg-gray-50 transition-colors"
                >
                  下一页
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }
}

export default UsersManagement;

补充说明

如果后续数据量过大,前端分页性能不足,可以改为后端分页:请求接口时携带page和pageSize参数,后端返回对应页数据和总条数即可,仅需要修改Axios请求逻辑和分页参数计算逻辑,前端UI不需要调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:36:07