React中单个无限滚动内两个useSwrInfinite钩子仅一个触发问题
问题:同一个自定义Hook中多个useSwrInfinite仅第一个触发请求
我需要构建一个无限滚动组件,从两个不同的分页数据源渲染卡片。加载逻辑是:用户滚动加载更多时,优先请求第一个数据源的下一页;当第一个数据源没有更多结果时,再请求第二个数据源的下一页。
为此我在同一个自定义Hook中两次调用useSwrInfinite,代码如下:
const useInfiniteFetchAlphasAndBetas = () => { const alphaData = useSwrInfinite( ... FETCH_ALPHAS_URL) const betaData = useSwrInfinite( ... FETCH_BETAS_URL) const hasMoreAlphaResults = alphaData?.length ? alphaData[alphaData.length - 1].pageInfo?.hasNextPage : false const hasMoreBetaResults = betaData?.length ? betaData[betaData.length - 1].pageInfo?.hasNextPage : false const hasMoreResults = hasMoreAlphaResults || hasMoreBetaResults const handleLoadMoreItems = () => { if(hasMoreAlphaResults) alphaData.setSize(alphaData.size + 1) else if(hasMoreBetaResults) betaData.setSize(betaData.size + 1) } return { alphaData, betaData, hasMoreResults, handleLoadMoreItems} }
但实际运行时发现:只有第一个调用的useSwrInfinite钩子会发起请求,第二个完全不触发;如果调换两个钩子的调用顺序,原来的第一个钩子就不再触发请求。请问是否无法在同一个自定义Hook中同时调用多个useSwrInfinite?
解决方案
这是因为useSwrInfinite的内部状态管理依赖于钩子的调用顺序和独立的实例上下文,当你在同一个自定义Hook中连续调用两个useSwrInfinite时,它们的内部状态(比如size)会互相干扰,导致只有第一个钩子能正常触发请求更新。
解决方法是将两个无限请求逻辑分开封装到独立的自定义Hook中,避免状态冲突:
// 单独封装第一个数据源的无限请求逻辑 const useInfiniteAlphas = () => { const alphaData = useSwrInfinite( (pageIndex, previousPageData) => { // 生成alpha数据源的分页请求key if (previousPageData && !previousPageData.pageInfo.hasNextPage) return null; return `${FETCH_ALPHAS_URL}?page=${pageIndex + 1}`; }, { revalidateFirstPage: false } ); const hasMore = alphaData.data?.length ? alphaData.data[alphaData.data.length - 1].pageInfo?.hasNextPage : false; return { ...alphaData, hasMore }; }; // 单独封装第二个数据源的无限请求逻辑 const useInfiniteBetas = () => { const betaData = useSwrInfinite( (pageIndex, previousPageData) => { // 生成beta数据源的分页请求key if (previousPageData && !previousPageData.pageInfo.hasNextPage) return null; return `${FETCH_BETAS_URL}?page=${pageIndex + 1}`; }, { revalidateFirstPage: false } ); const hasMore = betaData.data?.length ? betaData.data[betaData.data.length - 1].pageInfo?.hasNextPage : false; return { ...betaData, hasMore }; }; // 整合两个Hook的加载逻辑 const useInfiniteFetchAlphasAndBetas = () => { const alpha = useInfiniteAlphas(); const beta = useInfiniteBetas(); const hasMoreResults = alpha.hasMore || beta.hasMore; const handleLoadMoreItems = () => { if (alpha.hasMore) { alpha.setSize(alpha.size + 1); } else if (beta.hasMore) { beta.setSize(beta.size + 1); } }; return { alphaData: alpha, betaData: beta, hasMoreResults, handleLoadMoreItems }; };
原理说明
useSwrInfinite每个实例都会维护自己的size、data等内部状态,分开封装后,两个钩子的状态完全独立,不会互相干扰。在整合的Hook中,我们只需要根据各自的hasMore状态来触发对应的加载逻辑即可。
内容的提问来源于stack exchange,提问作者rocko1515
相关产品推荐
相关产品推荐

