You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:50:21