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

React Apollo Client点击下一页无法拉取分页数据如何解决?

修复方案

你遇到的问题核心是没有把分页参数做成响应式状态,useQuery会自动监听传入的variables变化,当page参数改变时会自动触发重新请求,不需要重复调用Hook。下面提供两种常用实现方案:


方案1:基础页码切换(点击下一页替换当前列表数据)

这是最符合你现有代码的轻量改造方案:

  1. 用React状态管理当前页码
  2. 把响应式的页码传入useCharacters
  3. 点击下一页只需要修改页码状态即可自动触发新请求

修改后的App.tsx代码:

import { useState } from 'react';
import { useCharacters } from './useCharacters';
// 你的列表组件,保持原有逻辑即可
import { CharacterList } from './CharacterList';

export const App = () => {
  // 用状态存储当前页码,默认第一页
  const [currentPage, setCurrentPage] = useState(1);
  const { data, loading, error } = useCharacters(currentPage);
  // 从接口返回值取总页数,做边界判断
  const totalPages = data?.characters?.info?.pages ?? 1;

  const nextPage = () => {
    // 防止超过总页数发起无效请求
    if (currentPage < totalPages) {
      setCurrentPage(prev => prev + 1);
    }
  };

  return (
    <>
      {loading ? (
        <div> Loading... </div>
      ) : error ? (
        <div>Error</div>
      ) : (
        <>
          <CharacterList data={data.characters.results} />
          {/* 到最后一页自动隐藏下一页按钮 */}
          {currentPage < totalPages && <div onClick={nextPage}> Next </div>}
        </>
      )}
    </>
  );
};

方案2:无限滚动追加(新数据拼接到现有列表尾部)

如果需要实现上拉加载更多、不覆盖原有列表的效果,可以直接用Apollo Client内置的fetchMoreAPI,不需要额外维护分页数据缓存:
首先修改useCharacters.tsx,把fetchMore方法暴露出来:

import { useQuery, gql } from '@apollo/client';

const GET_ALL_CHARACTERS = gql`
    query GetCharacters($page: Int) {
        characters(page: $page) {
            info {
                count
                pages
            }
            results {
                id
                name
            }
        }
    }
`;

export const useCharacters = (page: number = 1) => {
    const { data, loading, error, fetchMore } = useQuery(GET_ALL_CHARACTERS, { 
      variables: { page },
      // 开启网络状态变化通知,方便监听加载状态
      notifyOnNetworkStatusChange: true
    });
    return { data, loading, error, fetchMore };
};

然后修改App.tsx实现追加逻辑:

import { useCharacters } from './useCharacters';
import { CharacterList } from './CharacterList';

export const App = () => {
  const { data, loading, error, fetchMore } = useCharacters(1);
  const totalPages = data?.characters?.info?.pages ?? 1;
  // RickandMorty接口固定每页返回20条,以此计算当前已经加载到的页码
  const currentLoadedPage = data ? Math.ceil(data.characters.results.length / 20) : 1;

  const nextPage = async () => {
    const nextPageNum = currentLoadedPage + 1;
    if (nextPageNum > totalPages) return;
    // 调用fetchMore拉取下一页,自动合并到缓存
    await fetchMore({
      variables: { page: nextPageNum },
      updateQuery: (prevResult, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prevResult;
        return {
          characters: {
            ...prevResult.characters,
            info: fetchMoreResult.characters.info,
            // 新旧数据拼接
            results: [...prevResult.characters.results, ...fetchMoreResult.characters.results]
          }
        };
      }
    });
  };

  return (
    <>
      {loading ? (
        <div> Loading... </div>
      ) : error ? (
        <div>Error</div>
      ) : (
        <>
          <CharacterList data={data.characters.results} />
          {currentLoadedPage < totalPages && <div onClick={nextPage}> Next </div>}
        </>
      )}
    </>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:24:01