React Native FlatList滚动加载更多时useState更新报错问题
问题解决:FlatList滚动加载分页数据时追加列表出错
核心错误原因
你在追加新商品列表时,错误地将整个数组res.data.content作为单个元素添加到了products数组中,导致products变成了数组套数组的结构(比如[Product, Product, [Product, Product]]),而FlatList的renderItem期望接收单个ProductModel对象,因此渲染时抛出类型错误。
具体修复步骤
1. 修正数组展开方式
将错误的代码:
setProducts([...products, res.data.content]);
改为:
setProducts(prevProducts => [...prevProducts, ...res.data.content]);
- 用
...res.data.content展开新分页的数组元素,确保每个商品对象都被单独追加到列表中 - 使用函数式更新(
prevProducts => ...),避免异步回调中获取到过时的products状态值,保证每次追加都是基于最新的列表状态
2. 修复分页逻辑条件
原代码中if (currentPage >= maxNumberOfPages - 1)的逻辑完全颠倒,应该是当前页码小于总页数时才加载下一页,同时要加上!loading判断防止重复触发请求:
if (currentPage < maxNumberOfPages && !loading) { // 加载逻辑 }
注意:如果后端分页从0开始计数,初始currentPage建议设为0,加载完第一页后更新为1,以此类推。
3. 优化条件判断逻辑
原代码中两个独立的if可能导致重复执行,建议合并为更清晰的分支判断:
if (products.length === 0) { setProducts(res.data.content); setCurrentPage(currentPage + 1); setMaxNumberOfPages(res.data.totalPages); setLoading(false); } else if (res.data.numberOfElements > 0) { setProducts(prevProducts => [...prevProducts, ...res.data.content]); setCurrentPage(currentPage + 1); setLoading(false); }
修正后的完整getProductList函数
const getProductList = async () => { const token: string | null = await localStorage.getValue("token"); console.log("page:", currentPage); // 修正分页触发条件 if (currentPage < maxNumberOfPages && !loading) { setLoading(true); getAllProducts(token!, currentPage) .then((res) => { console.log( "res", res.data.numberOfElements, "totalPages: ", res.data.totalPages ); if (products.length === 0) { setProducts(res.data.content); setCurrentPage(currentPage + 1); setMaxNumberOfPages(res.data.totalPages); setLoading(false); } else if (res.data.numberOfElements > 0) { // 用函数式更新+正确展开数组 setProducts(prevProducts => [...prevProducts, ...res.data.content]); setCurrentPage(currentPage + 1); setLoading(false); } else { // 没有更多数据时停止加载 setLoading(false); } }) .catch((error) => { console.log("get products error:", error); setLoading(false); }); } };
额外优化建议
- 给FlatList加上
keyExtractor,避免渲染警告:keyExtractor={(item) => item.id.toString()} - 依靠
loading状态完全控制onEndReached的触发,防止快速滚动时多次发起重复请求
内容的提问来源于stack exchange,提问作者DarkSide77
相关产品推荐
相关产品推荐

