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

React Native FlatList无限滚动分页:底部加载指示器不显示问题排查

问题描述

我用React Native实现无限滚动分页加载数据,数据能正常加载,但底部的加载中和无更多数据指示器一直不显示。以下是我的代码,请问哪里出问题了?

状态定义:

const [page, setPage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
const [hasMoreData, setHasMoreData] = useState(true);

useEffect与数据获取:

useEffect(() => {
        fetchData();
    }, [page, searchText]);

    const fetchData = async () => {
        setIsLoading(true);
        try {
            const response = await axios.get(
                `https://dummy-api.php?search=${searchText}&page=${page}`
            );
            const data = response.data.data;

            if (page === 1) {
                setFilteredOptions(data);
            } else {
                setFilteredOptions((prevData) => [...prevData, ...data]);
            }

            if (data.length === 0) {
                setHasMoreData(false);
            }
        } catch (error) {
            console.error('Error fetching data:', error);
        }
        setIsLoading(false);
    };

渲染函数:

const renderItem = ({ item }) => (
        <TouchableOpacity
            key={item.id}
        >
            <Text style={styles.optionText}>{item.name}</Text>
        </TouchableOpacity>
    );

    const renderFooter = () => {
        if (!isLoading) return null;

        if (!hasMoreData) {
            return (
                <View>
                    <Text>No more data</Text>
                </View>
            );
        }

        return (
            <View>
                <ActivityIndicator />
            </View>
        );
    };

FlatList组件:

<FlatList
                    data={filteredOptions}
                    renderItem={renderItem}
                    keyExtractor={(item) => item.id.toString()}
                    onEndReached={fetchData}
                    onEndReachedThreshold={0.5}
                    ListFooterComponent={renderFooter}
                    showsVerticalScrollIndicator={false}
                />

问题分析与修复

你的代码存在三个核心问题,导致指示器无法正常显示:

1. 分页逻辑缺失,page从未递增

当前onEndReached直接调用fetchData,但没有更新page的值,每次请求的都是第1页数据,永远不会触发加载更多的追加逻辑,自然也不会触发hasMoreData的状态变更(除非第一页就返回空数据)。

修复:修改onEndReached回调,在允许加载时递增page:

// 替换原FlatList的onEndReached属性
onEndReached={() => {
  if (!isLoading && hasMoreData) {
    setPage(prev => prev + 1);
  }
}}

由于你的useEffect依赖page,page递增后会自动调用fetchData加载下一页,这才是正确的分页触发逻辑。

2. renderFooter逻辑顺序错误

现在的逻辑是只要不在加载状态就直接返回null,导致hasMoreData为false时(无更多数据),因为此时isLoading已变为false,"无更多数据"的提示根本不会渲染。

修复:调整判断顺序,优先处理无更多数据的情况:

const renderFooter = () => {
  // 无更多数据时直接显示提示
  if (!hasMoreData) {
    return (
      <View style={{padding: 16, alignItems: 'center'}}>
        <Text>没有更多数据了</Text>
      </View>
    );
  }
  // 正在加载时显示指示器
  if (isLoading) {
    return (
      <View style={{padding: 16, alignItems: 'center'}}>
        <ActivityIndicator />
      </View>
    );
  }
  // 其他情况返回空
  return null;
};

3. fetchData未阻止无效请求

当前fetchData没有判断isLoading和hasMoreData状态,可能导致重复发起请求,干扰状态更新,影响指示器显示。

修复:在fetchData开头增加拦截逻辑:

const fetchData = async () => {
  // 正在加载或无更多数据时,直接返回避免无效请求
  if (isLoading || !hasMoreData) return;
  
  setIsLoading(true);
  try {
    const response = await axios.get(
      `https://dummy-api.php?search=${searchText}&page=${page}`
    );
    const data = response.data.data;

    if (page === 1) {
      setFilteredOptions(data);
    } else {
      setFilteredOptions((prevData) => [...prevData, ...data]);
    }

    // 当前页返回空数据,标记无更多数据
    if (data.length === 0) {
      setHasMoreData(false);
    }
  } catch (error) {
    console.error('获取数据失败:', error);
  }
  setIsLoading(false);
};

可选优化:搜索时重置分页状态

当searchText变化时,重置分页相关状态,避免搜索新内容时加载旧分页数据:

useEffect(() => {
  setPage(1);
  setHasMoreData(true);
}, [searchText]);

内容的提问来源于stack exchange,提问作者Aashi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:32:02