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

如何将RTK Query响应与缓存数据追加整合,实现FlatList无限滚动并支持重取替换?

用RTK Query实现FlatList无限滚动的数据合并与重取替换

要实现无限滚动时合并新旧数据、重取时替换现有数据的需求,你可以通过两种方式处理:利用RTK Query的内置缓存配置,或者在组件内维护本地状态。以下是具体实现方案:

方案一:通过RTK Query的API配置实现全局缓存合并

这种方式适合需要全局共享分页数据的场景,不需要在组件内额外维护状态。

1. 修改API定义,配置合并与重取规则

首先在你的createApi定义中,给分页查询添加merge和forceRefetchBehavior配置:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const postsApi = createApi({
  reducerPath: 'postsApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
  endpoints: (builder) => ({
    getPosts: builder.query({
      // 传入分页参数:page(当前页)、limit(每页条数)、refresh(是否触发全量替换)
      query: ({ page, limit, refresh }) => `posts?page=${page}&limit=${limit}`,
      // 合并逻辑:新请求的分页数据追加到现有缓存末尾
      merge: (currentCache, newResponse) => {
        // 如果后端返回的是数组直接合并;如果是包含data的对象,调整为currentCache.data.push(...newResponse.data)
        currentCache.push(...newResponse);
      },
      // 重取替换规则:当refresh为true或首次请求时,用新数据完全替换旧缓存
      forceRefetch({ currentArg, previousArg }) {
        return currentArg?.refresh || !previousArg;
      },
      // 缓存保留时间,按需设置
      keepUnusedDataFor: 60,
    }),
  }),
});

export const { useGetPostsQuery } = postsApi;

2. 组件内使用查询,处理无限滚动与刷新

在FlatList组件中维护分页状态,触发请求并处理刷新逻辑:

import { useState } from 'react';
import { FlatList, ActivityIndicator } from 'react-native';
import { useGetPostsQuery } from './postsApi';

const PostList = () => {
  const [currentPage, setCurrentPage] = useState(1);
  const [isRefreshing, setIsRefreshing] = useState(false);

  // 传入分页参数,refresh为true时触发全量替换
  const { data: posts, isLoading, isFetching } = useGetPostsQuery(
    { page: currentPage, limit: 10, refresh: isRefreshing },
    { refetchOnMountOrArgChange: isRefreshing }
  );

  // 下拉刷新:重置页码并触发全量替换
  const handleRefresh = () => {
    setIsRefreshing(true);
    setCurrentPage(1);
    // 请求完成后重置刷新状态
    setTimeout(() => setIsRefreshing(false), 1000);
  };

  // 滚动到底部加载下一页
  const handleLoadMore = () => {
    if (!isLoading && !isFetching) {
      setCurrentPage(prev => prev + 1);
    }
  };

  return (
    <FlatList
      data={posts || []}
      renderItem={({ item }) => <PostItem post={item} />}
      keyExtractor={item => item.id.toString()}
      onRefresh={handleRefresh}
      refreshing={isRefreshing}
      onEndReached={handleLoadMore}
      onEndReachedThreshold={0.1}
      ListFooterComponent={isFetching ? <ActivityIndicator /> : null}
    />
  );
};

export default PostList;

方案二:组件内维护本地状态合并数据

如果不需要全局共享缓存,只在当前组件内处理数据合并,这种方式更灵活:

import { useState, useEffect } from 'react';
import { FlatList, ActivityIndicator } from 'react-native';
import { useGetPostsQuery } from './postsApi';

const PostList = () => {
  const [currentPage, setCurrentPage] = useState(1);
  const [allPosts, setAllPosts] = useState([]);
  const [isRefreshing, setIsRefreshing] = useState(false);

  const { data: newPosts, isLoading, isFetching } = useGetPostsQuery({
    page: currentPage,
    limit: 10
  });

  // 监听新数据,合并或替换本地状态
  useEffect(() => {
    if (newPosts) {
      if (currentPage === 1 || isRefreshing) {
        // 第一页或刷新时,用新数据替换全部
        setAllPosts(newPosts);
        setIsRefreshing(false);
      } else {
        // 加载更多时,追加新数据
        setAllPosts(prev => [...prev, ...newPosts]);
      }
    }
  }, [newPosts, currentPage, isRefreshing]);

  const handleRefresh = () => {
    setIsRefreshing(true);
    setCurrentPage(1);
  };

  const handleLoadMore = () => {
    if (!isLoading && !isFetching) {
      setCurrentPage(prev => prev + 1);
    }
  };

  return (
    <FlatList
      data={allPosts}
      renderItem={({ item }) => <PostItem post={item} />}
      keyExtractor={item => item.id.toString()}
      onRefresh={handleRefresh}
      refreshing={isRefreshing}
      onEndReached={handleLoadMore}
      onEndReachedThreshold={0.1}
      ListFooterComponent={isFetching ? <ActivityIndicator /> : null}
    />
  );
};

export default PostList;

注意事项

  • 确保你的后端接口支持分页参数(如page、limit),返回对应页的数据列表。
  • 如果后端返回的是包含总条数、数据列表的对象(如{ data: [], total: 100 }),需要调整merge函数或本地状态的合并逻辑,对应处理newPosts.data这类结构。
  • 方案一中的forceRefetch规则可根据实际需求修改,比如当页码回到1时自动触发全量替换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:20:53