React Apollo Client点击下一页无法拉取分页数据如何解决?
修复方案
你遇到的问题核心是没有把分页参数做成响应式状态,useQuery会自动监听传入的variables变化,当page参数改变时会自动触发重新请求,不需要重复调用Hook。下面提供两种常用实现方案:
方案1:基础页码切换(点击下一页替换当前列表数据)
这是最符合你现有代码的轻量改造方案:
- 用React状态管理当前页码
- 把响应式的页码传入
useCharacters - 点击下一页只需要修改页码状态即可自动触发新请求
修改后的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
相关产品推荐
相关产品推荐

