React Native无限滚动实现遇阻:useCallback引发渲染异常
React Native FlatList 无限滚动问题修复
你的问题核心是没处理好useCallback的依赖项和请求控制,导致要么出现依赖警告,要么函数异常执行。下面是修正后的完整代码,以及关键修改说明:
const HomeScreen = () => { const [next, setNext] = React.useState<string>(BASE_URL); const [isLoading, setIsLoading] = React.useState<boolean>(true); const [displayItems, setDisplayItems] = React.useState<Item[]>([]); // 初始化为空数组,简化后续逻辑 // 用useCallback包裹,明确依赖项 const fetchItems = React.useCallback(async () => { // 拦截重复请求和无下一页的情况 if (isLoading || !next) return; try { setIsLoading(true); const response = await client(next, 'GET'); // 合并新数据到已有列表 setDisplayItems(prevItems => [...prevItems, ...response.data]); // 更新下一页地址,若为最后一页则response.next应为null/undefined setNext(response.next); } catch (error) { console.error('加载失败:', error); // 这里可添加用户提示,比如Toast } finally { setIsLoading(false); } }, [next, isLoading]); // 初始加载,仅执行一次 React.useEffect(() => { fetchItems(); }, []); // 初始加载状态:全屏显示加载器 if (isLoading && displayItems.length === 0) { return <LoadingSpinner />; } // 无数据状态 if (displayItems.length === 0) { return <Text>暂无内容</Text>; } return ( <FlatList onEndReachedThreshold={0.1} // 滚动到距离底部10%时触发,提升体验 onEndReached={fetchItems} data={displayItems} renderItem={({ item }) => <ShowItem item={item} />} // 列表底部显示加载状态 ListFooterComponent={isLoading ? <SmallLoadingSpinner /> : null} /> ); }; export default HomeScreen;
关键修改说明
- 状态初始化优化:把
displayItems初始值设为空数组,避免后续拼接数据时的null判断,逻辑更简洁。 - useCallback依赖处理:明确将
next和isLoading加入依赖项,确保函数能捕获最新的状态值,同时避免不必要的重创建。 - 请求拦截逻辑:添加
if (isLoading || !next) return,防止重复请求(比如用户快速滚动多次触发加载),也避免在没有下一页时发起无效请求。 - 初始加载控制:初始加载的
useEffect依赖空数组,确保只执行一次,不会因为fetchItems的变化重复触发。 - 加载状态优化:区分初始全屏加载和后续列表底部加载,提升用户体验;调整
onEndReachedThreshold为0.1,让加载触发更及时。
内容的提问来源于stack exchange,提问作者Sharon
相关产品推荐
相关产品推荐

