React Native BigList停止加载 未触发onEndReached问题
问题原因
你的代码存在4个核心逻辑漏洞,才会导致滚动几次后加载停止:
- 闭包陷阱:
getData函数内读取的pageNumber、loading、homeImages都是函数创建时的旧状态值,不是最新的实时值,滚动几次后状态值和实际值偏差越来越大,会出现加载锁判断错误、页码计算错误的问题 - 加载锁死:原代码
catch分支没有重置loading状态,只要出现一次请求报错,loading就会永久为true,后续触发getData时会直接跳过请求逻辑 - 触发阈值缺失:
BigList默认的onEndReached触发阈值极小,只有滚动到列表最底部边缘才会触发,快速滚动时很容易错过判定点,导致回调不执行 - 状态更新竞态:原代码直接用
setHomeImages([...homeImages, ...responseJson])的写法,多次快速触发加载时会出现新返回的数据覆盖之前已加载数据的问题
修复后代码
import React, { useEffect, useState } from 'react'; import { View, Text, Image, Dimensions } from 'react-native'; import BigList from 'react-native-big-list'; const HomeScreen = ({ navigation }) => { const BaseURL = "http://localhost:12646/" const windowWidth = Dimensions.get('window').width; const [homeImages, setHomeImages] = useState([]); const [pageNumber, setPageNumber] = useState(1); const [loading, setLoading] = useState(false); useEffect(() => { getData(); }, []); const getData = () => { if (loading) return; setLoading(true); const url = `${BaseURL}api/images/GetHomepageImages?PageNumber=${pageNumber}&PageSize=3`; fetch(url) .then((response) => response.json()) .then((responseJson) => { // 函数式更新状态,规避闭包旧值问题 setPageNumber(prev => prev + 1); setHomeImages(prev => [...prev, ...responseJson]); setLoading(false); }) .catch((error) => { console.error(error); // 必须重置loading,否则请求失败后锁死 setLoading(false); }); } const renderItem = ({ item, index }) => { return ( <View style={{ height: windowWidth }}> <Image style={{ width: windowWidth, height: windowWidth }} source={{ uri: `${BaseURL}images/${item.basePath}/${item.imageSquare}` }} /> </View> ); } const keyExtractor = (item, index) => item.id?.toString() || index.toString(); return ( <View style={{flex: 1}}> { homeImages.length > 0 ? <BigList data={homeImages} onEndReached={getData} onEndReachedThreshold={0.5} // 距离底部半个列表高度时提前触发加载 itemHeight={windowWidth} renderItem={renderItem} keyExtractor={keyExtractor} /> : <Text>Loading</Text> } </View> ) }; export default HomeScreen;
关键修改说明
- 所有依赖之前状态的更新操作都改用函数式写法,彻底解决闭包旧值导致的逻辑错误
- 补全请求异常分支的
loading重置逻辑,避免加载状态永久锁死 - 新增
onEndReachedThreshold={0.5}配置,将加载触发时机提前,避免快速滚动错过回调判定 - 修正了原来
setOffset的错误命名,统一为setPageNumber和状态名语义对齐 - 新增
keyExtractor属性,保证列表内部渲染计算的稳定性,减少列表高度判定偏差 - 空状态判断从
homeImages != null改为homeImages.length > 0,逻辑更准确,避免初始空数组时一直显示Loading
内容的提问来源于stack exchange,提问作者Shazoo
相关产品推荐
相关产品推荐

