react-window中<List>组件的异步fetch/axios数据代码应放于何处?
React-Window
- 组件异步数据请求的放置位置
根据react-window的使用场景,异步数据请求的代码位置分为两种核心情况:
1. 基础列表(非无限加载)
直接在包含<List>的父组件的useEffect钩子中发起请求:
- 用
useState维护数据列表、加载状态等状态 - 在
useEffect中调用fetch或axios获取数据,请求完成后更新状态 - 将数据和状态传递给
<List>的itemCount(总条数)和itemRenderer(渲染每一项)
示例代码:
import { useState, useEffect } from 'react'; import { FixedSizeList as List } from 'react-window'; function MyList() { const [items, setItems] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchData = async () => { try { const response = await fetch('/api/data'); const data = await response.json(); setItems(data); } catch (err) { console.error('请求失败:', err); } finally { setIsLoading(false); } }; fetchData(); }, []); if (isLoading) return <div>加载中...</div>; return ( <List height={500} itemCount={items.length} itemSize={50} width={300} > {({ index, style }) => ( <div style={style}> {items[index].content} </div> )} </List> ); }
2. 无限加载列表(搭配InfiniteLoader)
如果使用react-window-infinite-loader实现滚动加载,请求逻辑要放在InfiniteLoader的loadMoreItems配置项中:
- 用
isItemLoaded判断某条数据是否已加载(用来确定哪些项需要触发加载) - 在
loadMoreItems中发起异步请求,获取新数据后合并到现有列表中 - 注意控制请求并发,避免重复触发加载
示例代码:
import { useState, useCallback } from 'react'; import { FixedSizeList as List } from 'react-window'; import InfiniteLoader from 'react-window-infinite-loader'; function InfiniteScrollList() { const [items, setItems] = useState([]); const [hasMore, setHasMore] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); const pageSize = 20; // 判断项是否已加载 const isItemLoaded = useCallback((index) => { return index < items.length; }, [items.length]); // 加载更多数据 const loadMoreItems = useCallback(async () => { if (isLoadingMore || !hasMore) return; setIsLoadingMore(true); try { const response = await fetch(`/api/data?page=${Math.floor(items.length / pageSize) + 1}&size=${pageSize}`); const newData = await response.json(); if (newData.length < pageSize) { setHasMore(false); } setItems(prev => [...prev, ...newData]); } catch (err) { console.error('加载更多失败:', err); } finally { setIsLoadingMore(false); } }, [items.length, isLoadingMore, hasMore, pageSize]); return ( <InfiniteLoader isItemLoaded={isItemLoaded} itemCount={hasMore ? items.length + pageSize : items.length} loadMoreItems={loadMoreItems} > {({ onItemsRendered, ref }) => ( <List ref={ref} height={500} itemCount={hasMore ? items.length + pageSize : items.length} itemSize={50} width={300} onItemsRendered={onItemsRendered} > {({ index, style }) => { if (!isItemLoaded(index)) { return <div style={style}>加载中...</div>; } return <div style={style}>{items[index].content}</div>; }} </List> )} </InfiniteLoader> ); }
关键注意事项
- 避免重复请求:通过加载状态锁(如
isLoading、isLoadingMore)防止同一时间发起多个请求 - 错误处理:给请求添加
try/catch,处理网络失败或接口报错的情况 - 加载状态反馈:在请求过程中显示加载提示,提升用户体验
内容的提问来源于stack exchange,提问作者yeln
相关产品推荐
相关产品推荐

