React+Node结合Redux状态实现加载更多按钮的问题求解
问题分析与解决方案
问题1:旧数据无法保留、修改合并逻辑后报类型错误
原因
- 原Reducer逻辑每次拉取新数据后直接覆盖
products和originalItems字段,旧数据自然被清除 - 合并数组时报错是因为Reducer初始状态中没有给
products、originalItems设置默认空数组,首次加载时state.products为undefined,展开undefined会直接抛出类型错误 - 额外注意:需确保接口返回的
payload.data是标准商品数组,若后端接口返回格式嵌套层级错误也会导致合并失败
修复方案
- 先修正Reducer的初始状态,给列表字段设置默认空数组
- 合并数组时添加兜底逻辑,避免偶发的undefined报错
- 后端接口需要返回商品总数量,用来后续判断是否还有更多数据可加载
修正后Reducer代码:
// 初始状态示例 const initialState = { products: [], originalItems: [], total: 0, // 新增字段存商品总数量 // 其余原有状态保持不变 } // PRODUCT_FETCH分支逻辑 case "PRODUCT_FETCH": return { ...state, products: [...(state.products || []), ...payload.data], originalItems: [...(state.originalItems || []), ...payload.data], total: payload.total // 存储后端返回的总数量 };
修正后后端返回逻辑:
const { skip, limit } = req.body; let products = await Product.find() .populate("category") .skip(skip) .limit(limit); let productsLength = await Product.find().countDocuments(); // 调整返回格式,同时返回商品列表和总数量 res.json({ data: products, total: productsLength })
问题2:skip参数不递增、重复拉取最后一页数据
原因
你当前使用的Skip变量没有存入组件状态,在handleLoadMore中计算完新的skip值后没有更新存储的Skip变量,下次触发加载时还是用初始值计算,导致每次请求的分页参数完全相同。
修复方案
将Skip存入组件的useState状态,每次加载新数据后更新状态值,同时新增是否还有更多数据的判断,避免无效请求。
修正后ProductList.jsx代码:
import { useState, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' const ProductList = () => { const dispatch = useDispatch() // 从Redux取商品列表、总数量 const { products, total } = useSelector(state => state.product) // 把skip存入组件状态,初始值为0 const [Skip, setSkip] = useState(0) // 分页大小可根据需求调整 const Limit = 10 const [filterProduct, setFilterProduct] = useState([]) // 控制是否还有更多数据可加载 const [hasMore, setHasMore] = useState(true) useEffect(() => { setFilterProduct(products); // 每次商品列表更新后判断是否还有剩余数据未加载 setHasMore(products.length < total) }, [products, total]); useEffect(() => { const data = { skip: Skip, limit: Limit, }; dispatch(fetchNewProducts(data)); }, []); const handleLoadMore = () => { // 没有更多数据时直接终止请求 if(!hasMore) return const newSkip = Skip + Limit; // 更新skip状态,保证下次加载用新的参数计算 setSkip(newSkip) const data = { skip: newSkip, limit: Limit, }; dispatch(fetchNewProducts(data)); }; // 渲染逻辑可自行调整,加载更多按钮建议加 disabled={!hasMore} 状态 return ( {/* 商品列表渲染 */} <button onClick={handleLoadMore} disabled={!hasMore}> {hasMore ? '加载更多' : '没有更多商品了'} </button> ) }
内容的提问来源于stack exchange,提问作者Sreerag Pavithran
相关产品推荐
相关产品推荐

