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

React JS实现医生列表每页10条分页及按经验筛选功能开发问题

React医生列表分页+筛选功能实现方案

核心修改逻辑

  • 新增originalData状态存储全量接口返回数据,避免筛选后丢失原始数据
  • 新增selectedExp状态存储选中的经验筛选条件
  • 新增currentPage状态存储当前分页页码,默认值为1
  • 固定每页展示条数为10,新增pageSize常量
  • 先根据筛选条件过滤全量数据,再对过滤后的数据做分页切片
  • 给经验选择器、分页按钮绑定交互事件

完整修改后代码

import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import DocPic from "../img/doctor.png";
import InnerDetail from "./innerto_detail";
import axios from "axios";
export default function InnerSpecialities() {
 const [hasId, setHasId] = useState(false);
 const [detail, setDetail] = useState(false);
 // 新增原始全量数据存储
 const [originalData, setOriginalData] = useState([]);
 // 新增经验筛选选中值
 const [selectedExp, setSelectedExp] = useState("all");
 // 新增分页相关状态
 const [currentPage, setCurrentPage] = useState(1);
 const pageSize = 10;
 const inipath = window.location.pathname;
 const id_path = inipath.split("/cdoctor/details");
 const path = inipath.split("/cdoctor/");
 useEffect(() => {
   const pathname = window.location.pathname;
   const doctorId = pathname.split("/")[2];
   console.log("this is the ", doctorId);
   console.log(id_path);
   const substring = "detiled";
   console.log(inipath.includes(substring));
   if (inipath.includes(substring) === true) {
     setDetail(true);
   }
   const config = {
     headers: {
       Authorization: `token ` + localStorage.getItem("token"),
     },
   };

   axios
     .get(
       "filter/?speciality=" +
         path[1],
       config
     )
     .then((res) => {
       // 存储原始全量数据
       setOriginalData(res.data);
     });
 }, []);

 function OpenInner() {
   setDetail(true);
 }

 // 筛选逻辑:根据经验过滤数据
 const filteredData = originalData.filter(item => {
   if(selectedExp === "all") return true;
   const exp = Number(item.experience);
   switch(selectedExp) {
     case "0-5": return exp >=0 && exp <5;
     case "5-10": return exp >=5 && exp <10;
     case "10-15": return exp >=10 && exp <15;
     case "15+": return exp >=15;
     default: return true;
   }
 })

 // 分页逻辑:计算当前页展示的数据
 const startIndex = (currentPage -1) * pageSize;
 const endIndex = startIndex + pageSize;
 const paginatedData = filteredData.slice(startIndex, endIndex);
 // 计算总页数
 const totalPage = Math.ceil(filteredData.length / pageSize);

 // 筛选条件变更时重置页码为第一页
 const handleExpChange = (e) => {
   setSelectedExp(e.target.value);
   setCurrentPage(1);
 }

 return (
   <>
     {detail ? (
       <InnerDetail />
     ) : (
       <div>

         <div>
           <div className="list-container" style={styles.options}>
          

             <div style={styles.inneropt}>
               <i style={styles.rotate} class="fa fa-exchange"></i>Sort By:
               <select style={styles.sel}>
                 <option> Availability</option>
                 <option> Nearby</option>
                 <option> Price- Low to high</option>
                 <option> Price- High to low</option>
               </select>{" "}
             </div>
             <div style={styles.inneropt}>
               Gender:
               <select style={styles.sel}>
                 <option> Male</option>
                 <option> Female</option>
               </select>{" "}
             </div>
             <div style={styles.inneropt}>
               Experience:
               {/* 绑定筛选值和变更事件 */}
               <select style={styles.sel} value={selectedExp} onChange={handleExpChange}>
                 <option value="all">全部</option>
                 <option value="0-5"> 0-5</option>
                 <option value="5-10"> 5-10</option>
                 <option value="10-15"> 10-15</option>
                 <option value="15+"> 15+ </option>
               </select>{" "}
             </div>
             <div className="splang" style={styles.inneropt}>
               Language:
               <select style={styles.sel}>
                 <option> English</option>
                 <option> Malayaliam</option>
                 <option> Tamil</option>
                 <option> Kannada</option>
               </select>{" "}
             </div>
           </div>

           <div style={styles.container}>
             {/* 渲染当前页的筛选后数据 */}
             {paginatedData.map((personData, key) => {
               return (
                 <div style={styles.fbox} key={key}>
                   <div style={styles.fitem}>
                     <left>
                       <img src={DocPic} alt="" />
                       <br />
                       <i className="fa fa-video-camera"></i>
                       <br />
                       <small>Online</small>
                     </left>
                     <right style={{ textAlign: "left", marginLeft: "6px" }}>
                       <strong>
                         Dr {personData.firstname}&nbsp;
                         {personData.lastname}
                       </strong>
                       <br />
                       <small>
                         {" "}
                         {personData.speciality} |{personData.experience}
                         <small> years Exp.</small>
                       </small>
                       <br />
                       <strong>You Pay</strong>
                       <br />
                       <strong>$600</strong>
                       <br />
                       <small>
                         {personData.qualification}
                         {personData.location}
                       </small>
                     </right>
                   </div>
                   <Link
                     to={{
                       pathname: "/doctor/detiled/" + personData.id,
                       state: { id: personData.id, data: personData },
                     }}
                     onClick={OpenInner}
                   >
                     <button style={styles.book}>Book Appointments</button>
                   </Link>
                 </div>
               );
             })}
           
           </div>

           <div style={styles.pagination} className="pagination">
             <div className="pager" style={{ margin: "auto", width: "30rem" }}>
               {/* 上一页按钮,第一页时禁用点击 */}
               <Link to="" onClick={(e) => {
                 e.preventDefault();
                 if(currentPage >1) setCurrentPage(currentPage -1)
               }}>
                 {" "}
                 <i className="fa fa-angle-left"></i>{" "}
               </Link>
               {/* 动态渲染页码 */}
               {Array.from({length: totalPage}, (_,i) => i+1).map(page => (
                 <Link 
                   to="" 
                   key={page}
                   style={{fontWeight: page === currentPage ? 'bold' : 'normal'}}
                   onClick={(e) => {
                     e.preventDefault();
                     setCurrentPage(page)
                   }}
                 >
                   {page}
                 </Link>
               ))}
               {/* 下一页按钮,最后一页时禁用点击 */}
               <Link to="" onClick={(e) => {
                 e.preventDefault();
                 if(currentPage < totalPage) setCurrentPage(currentPage +1)
               }}>
                 {" "}
                 <i className="fa fa-angle-right"></i>{" "}
               </Link>
             </div>
           </div>
         </div>
       </div>
     )}
   </>
 );
}

注意事项

  • 代码中默认医生数据的experience字段是数字类型,若接口返回的是字符串,需要在过滤前先做类型转换
  • 原有代码中冗余的setdata逻辑已清理,统一用originalData存储全量接口数据
  • 分页部分改为动态生成页码,不再固定显示7个页码,会根据筛选后的数据总条数自动计算总页数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:15:07