React分类切换分页异常:分页消失且无法统计分类总页数
React分类分页异常修复方案
问题现象
点击分类按钮后分页组件消失,且无法正确统计当前分类下的总页数。
前端修复步骤
1. 修正分页计数的响应式逻辑
原代码中count变量的赋值未跟随分类状态实时更新,需将其改为响应式判断:
// 替换原count变量定义,放在组件内部(useState之后) const count = category ? filteredContentCount : contentsCount;
2. 修复分页组件的总项数参数
分页组件的totalItemsCount需使用当前分类对应的总条数,而非全量内容总数:
{(resPerPage <= count) && ( <div className="d-flex justify-content-center mt-5"> <Pagination activePage={currentPage} itemsCountPerPage={resPerPage} totalItemsCount={count} // 替换为count,匹配当前分类总条数 onChange={setCurrentPageNo} nextPageText={'Next'} prevPageText={'Prev'} firstPageText={'First'} lastPageText={'Last'} itemClass="page-item" linkClass="page-link" /> </div> )}
3. 分类切换时重置页码
切换分类后重置页码为第一页,避免出现空数据页:
function setCategories(category) { setCurrentPage(1); // 新增页码重置逻辑 setCategory(category); }
后端修复步骤
1. 正确计算分类下的总条数
原代码中filteredContentCount取的是分页后的数据长度,并非分类下的总条数。需在分页前单独查询分类过滤后的总数量:
exports.getContents = asyncErrors(async (req, res, next) => { const resPerPage = 9; // 构建完整过滤条件(复用APIFeatures的过滤逻辑) let filterQuery = {}; // 处理搜索关键词 if (req.query.keyword) { filterQuery.name = { $regex: req.query.keyword, $options: 'i' }; } // 处理其他过滤参数 const queryCopy = { ...req.query }; const removeFields = ['keyword', 'limit', 'page']; removeFields.forEach(el => delete queryCopy[el]); let queryStr = JSON.stringify(queryCopy); queryStr = queryStr.replace(/\b(gt|gte|lt|lte)\b/g, match => `$${match}`); Object.assign(filterQuery, JSON.parse(queryStr)); // 计算全量总数和分类过滤后的总数 const contentsCount = await Content.countDocuments(); const filteredContentCount = await Content.countDocuments(filterQuery); // 执行分页查询 const apiFeatures = new APIFeatures(Content.find(filterQuery), req.query) .pagination(resPerPage); const contents = await apiFeatures.query; res.status(200).json({ success: true, contents, contentsCount, resPerPage, filteredContentCount }); });
2. 优化APIFeatures类(可选)
抽离过滤逻辑,避免后端代码重复:
class APIFeatures { constructor(query, queryStr) { this.query = query; this.queryStr = queryStr; this.filterQuery = {}; // 存储过滤条件 } search() { const keyword = this.queryStr.keyword ? { name: { $regex: this.queryStr.keyword, $options: 'i' } } : {}; Object.assign(this.filterQuery, keyword); this.query = this.query.find(this.filterQuery); return this; } filter() { const queryCopy = { ...this.queryStr }; const removeFields = ['keyword', 'limit', 'page']; removeFields.forEach(el => delete queryCopy[el]); let queryStr = JSON.stringify(queryCopy); queryStr = queryStr.replace(/\b(gt|gte|lt|lte)\b/g, match => `$${match}`); Object.assign(this.filterQuery, JSON.parse(queryStr)); this.query = this.query.find(this.filterQuery); return this; } pagination(resPerPage) { const currentPage = Number(this.queryStr.page) || 1; const skip = resPerPage * (currentPage - 1); this.query = this.query.limit(resPerPage).skip(skip); return this; } // 获取最终过滤条件 getFilterQuery() { return this.filterQuery; } } module.exports = APIFeatures;
优化后后端调用方式:
const apiFeatures = new APIFeatures(Content.find(), req.query).search().filter(); const filteredContentCount = await Content.countDocuments(apiFeatures.getFilterQuery()); apiFeatures.pagination(resPerPage); const contents = await apiFeatures.query;
验证要点
- 点击分类按钮,页码自动重置为1,分页组件显示当前分类的总页数
- 切换分类时,分页组件正常显示,页数计算准确
- 分页切换时,加载对应分类的对应页数据
内容的提问来源于stack exchange,提问作者ThatGuyNick
相关产品推荐
相关产品推荐

