React分页跳转非首页后搜索返回空结果问题排查修复
问题根因
- 搜索作用域错误:
users状态仅存储当前分页的10条数据,翻页后该状态仅保留对应页内容,前端搜索直接在users上做过滤,无法匹配到其他分页的结果,非首页搜索自然返回空。 - 搜索未重置分页:非首页状态下offset不为0,触发搜索后分页切片仍从非0位置开始,就算有匹配结果也会被切片逻辑漏掉。
- 分页参数固定:
pageCount始终按全量数据长度计算,搜索后结果总数变化时不会动态更新,容易出现空页。 - 状态更新不规范:全选逻辑中多余调用
getApiData()会覆盖本地增删改后的用户数据;onCheckHandler中直接修改状态数组的元素,违反React状态不可变原则,会引发渲染异常。
修改方案
- 数据分层存储:接口仅在组件初始化时拉取一次全量用户数据存入
apid,所有搜索过滤先在全量数据上执行,再做分页切片,禁止在单页数据上做全局搜索。 - 搜索自动归位:触发搜索时将分页偏移量
offset重置为0,强制回到第一页展示搜索结果。 - 动态计算分页值:当前页展示数据、总页数都基于搜索过滤后的结果集计算,随搜索关键词变化实时更新。
- 修正不规范状态更新:移除全选逻辑中多余的接口调用,所有状态修改采用不可变更新方式,避免直接赋值原状态数组。
核心修正代码
1. 调整数据拉取逻辑
接口仅初始化时拉取一次全量数据,翻页不再重复请求:
const getApiData = async () => { const res = await axios.get('https://geektrust.s3-ap-southeast-1.amazonaws.com/adminui-problem/members.json'); setApid(res.data); } // 移除useEffect的offset依赖 useEffect(() => { getApiData(); }, []);
2. 新增统一的过滤、分页计算逻辑
用useMemo缓存计算结果,避免重复计算:
import { useEffect, useMemo, useRef, useState } from "react"; // 记得引入useMemo // 搜索过滤后的全量结果 const filteredUsers = useMemo(() => { if (!apid) return []; if (!searchValue?.trim()) return apid; const keyword = searchValue.toLowerCase().trim(); return apid.filter(user => user.name.toLowerCase().includes(keyword) || user.email.toLowerCase().includes(keyword) || user.role.toLowerCase().includes(keyword) ) }, [apid, searchValue]); // 当前分页需要展示的数据 const currentPageUsers = useMemo(() => { return filteredUsers.slice(offset, offset + perPage); }, [filteredUsers, offset, perPage]); // 搜索结果对应的总页数 const currentPageCount = useMemo(() => { return Math.ceil(filteredUsers.length / perPage); }, [filteredUsers.length, perPage]);
3. 修正搜索、分页、全选逻辑
// 搜索时重置到第一页 const searchList = () => { setSearchValue(searchRef.current.value); setOffset(0); }; // 分页点击逻辑适配动态结果长度 const handlePageClick = (e) => { const selectedOffset = e.selected * perPage; setOffset(Math.min(selectedOffset, filteredUsers.length)); }; // 全选逻辑移除多余接口调用 const selectAllVisibleUserRecord = () => { setIsCheckAll(prev => !prev); if (isCheckAll) { setIds([]); return; } setIds(currentPageUsers.map(user => user.id)); }; // 修正编辑用户时的状态更新,不直接修改原数组 const onCheckHandler = userRecord => { setUsers(prev => { const existIndex = prev.findIndex(record => record.id === userRecord.id); if (existIndex === -1) return [userRecord, ...prev]; const newList = [...prev]; newList[existIndex] = userRecord; return newList; }) }
4. 调整渲染部分逻辑
移除表格遍历前多余的filter,直接使用计算好的当前页数据,分页组件传入动态总页数:
{/* 表格内容部分 */} <tbody> {currentPageUsers.map((listdata) => ( <tr key={listdata.id} className={ids.includes(listdata.id) ? 'checked' : ''}> {/* 原有行内容保持不变 */} </tr> ))} </tbody> {/* 分页组件部分 */} <ReactPaginate previousLabel={"prev"} nextLabel={"next"} breakLabel={"..."} breakClassName={"break-me"} pageCount={currentPageCount} {/* 替换原来的固定pageCount */} pageRangeDisplayed={5} onPageChange={handlePageClick} containerClassName={"pagination"} subContainerClassName={"pages pagination"} activeClassName={"active"} />
内容的提问来源于stack exchange,提问作者user2568391
相关产品推荐
相关产品推荐

