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

使用FlatList实现无限滚动时加载更多数据致应用无响应

React Native FlatList无限滚动UI无响应问题解决方案

问题根源分析

  • 重复加载同一页数据:handleLoadMore中page固定为1,每次加载都是第一页数据,重复累加会导致FlatList重渲染时阻塞UI线程。
  • 错误混用Apollo缓存与本地状态:直接在updateQuery里调用setUsers,导致Apollo缓存更新和本地状态更新冲突,引发不必要的重渲染,加重UI负担。
  • 无重复请求拦截:滚动到底部时可能多次触发onEndReached,同时发起多个请求,阻塞JS线程,导致点击事件、日志输出完全无响应。
  • 初始渲染配置不合理:initialNumToRender设为1,会让FlatList频繁触发渲染,进一步消耗UI资源。

解决方案

  1. 跟踪页码并递增:用状态保存当前页码,每次加载更多时自动+1,确保请求下一页数据。
  2. 依赖Apollo缓存管理数据:移除本地users状态,直接使用useQuery返回的data,由Apollo自动处理缓存和数据更新,避免状态不一致。
  3. 添加加载状态锁:维护isLoadingMore状态,防止请求未完成时重复触发加载。
  4. 正确实现updateQuery:返回合并后的查询结果,让Apollo自动更新缓存,组件从缓存获取最新数据。
  5. 优化FlatList属性:调整initialNumToRender为合理值,减少初始渲染压力;设置合适的onEndReachedThreshold,避免过早/过晚触发加载。

修改后的完整代码

import { FlatList, Text } from "react-native";
import * as S from "./styles";
import { useQuery } from "@apollo/client";
import { searchUsers } from "src/services/users/graphql/query";
import React, { useState } from "react";
import { getImagePathFromObj } from "@helpers/getImagePath";

export const Playground = () => {
    const [currentPage, setCurrentPage] = useState(1);
    const [isLoadingMore, setIsLoadingMore] = useState(false);
    
    const { loading, error, data, fetchMore } = useQuery(searchUsers, {
        variables: {
            name: "",
            latestLatitude: 64.71998823308158,
            latestLongitude: 175.5945099215997,
            page: currentPage,
        },
        onError: (error) => {
            console.error("Error fetching users:", error);
        },
    });

    const handleLoadMore = async () => {
        if (isLoadingMore) return; // 拦截重复请求
        setIsLoadingMore(true);
        
        try {
            await fetchMore({
                variables: {
                    name: "",
                    latestLatitude: 64.71998823308158,
                    latestLongitude: 175.5945099215997,
                    page: currentPage + 1,
                },
                updateQuery: (previousResult, { fetchMoreResult }) => {
                    if (!fetchMoreResult?.searchUsers) return previousResult;
                    
                    // 返回合并结果,让Apollo自动更新缓存
                    return {
                        searchUsers: [...previousResult.searchUsers, ...fetchMoreResult.searchUsers]
                    };
                },
            });
            setCurrentPage(prev => prev + 1);
        } catch (err) {
            console.error("Error loading more users:", err);
        } finally {
            setIsLoadingMore(false);
        }
    };

    const RenderItem = React.memo(({ item }) => {
        return (
            <S.Profile onPress={() => console.log("press")}>
                <S.ProfileImage source={{ uri: getImagePathFromObj(item) }} />
            </S.Profile>
        );
    });

    return (
        <S.Container>
            {loading && !isLoadingMore && <Text>Loading...</Text>}
            {error && <Text>Error loading users</Text>}
            <FlatList
                data={data?.searchUsers || []}
                renderItem={({ item }) => <RenderItem item={item} />}
                keyExtractor={(item) => item.id.toString()}
                numColumns={2}
                onEndReached={handleLoadMore}
                onEndReachedThreshold={0.5}
                initialNumToRender={10}
                ListFooterComponent={isLoadingMore && <Text>Loading more...</Text>}
            />
        </S.Container>
    );
};

关键修改说明

  • 移除本地users状态,直接使用Apollo返回的data,避免状态冲突。
  • 新增currentPage和isLoadingMore状态,分别控制页码和请求锁。
  • updateQuery正确返回合并结果,让Apollo自动管理缓存更新。
  • 优化FlatList配置,添加底部加载提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:17:07