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

useSWRInfinite的getKey函数pageIndex始终为1的问题求助

问题原因

你代码里的核心问题出在getKey函数的定义上,共3处错误:

  1. 参数定义错误
    useSWRInfinite 只会给getKey传递两个参数:pageIndex(当前页索引,从0开始计数)、previousPageData(上一页接口返回的数据)。你额外声明的第三个形参category是不存在的,实际取值为undefined,导致生成的分页key重复,SWR会认为你一直请求同一页数据,所以pageIndex不会增长。
  2. 终止条件和你的接口返回结构不匹配
    从你后续处理数据的写法data ? [].concat(...data) : []可以看出,你的getNearbyShops接口直接返回店铺数组,你写的终止判断if (previousPageData && !previousPageData.data) return null中的.data字段根本不存在,该条件永远不会生效。
  3. getKey没有做缓存
    getKey直接在组件内部定义,依赖props.category,如果不做缓存,组件每次重渲染都会生成新的getKey实例,导致useSWRInfinite内部状态被重置,分页逻辑异常。

修正后的完整代码

import React, { useCallback } from 'react'
import {useSelector} from 'react-redux'
import useSWRInfinite from 'swr/infinite'
import {Button, Grid, Typography} from '@material-ui/core'
import getNearbyShops from '../../../lib/nearshop-apis.js'
import ShopThumbnail from './shop-thumbnail.js'
import Spacer from '../../../components/utils/spacer'

const PAGE_SIZE=10

export default function Nearbyshops({category, categoryName}) {
  // 修正getKey:用useCallback缓存,去掉多余形参,直接取闭包中的category,修正终止条件
  const getKey = useCallback((pageIndex, previousPageData) => {
    console.log("getKey::pageIndex", pageIndex)
    // 上一页数据存在且长度小于页长,说明没有更多数据,终止加载
    if (previousPageData && previousPageData.length < PAGE_SIZE) return null
    return [`/api/nearbyshops/${pageIndex+1}`, pageIndex+1, PAGE_SIZE, category]
  }, [category])


  const {data, error, size, setSize} = useSWRInfinite(getKey, getNearbyShops)

  const shops = data ? [].concat(...data) : [];
  const isLoadingInitialData = !data && !error;
  const isLoadingMore =
          isLoadingInitialData || (size > 0 && data && typeof data[size-1] === 'undefined')
  const isEmpty = data?.[0]?.length === 0;
  const isReachingEnd =
        isEmpty || (data && data[data.length-1].length < PAGE_SIZE);

  const currentShop = useSelector(state => state.main.currentShop);
  const bg = currentShop.sColor
  const fg = currentShop.pColor
  const title = categoryName?`NEAR BY ${categoryName} SHOPS`:'NEAR BY SHOPS'

  return (
    <Grid>
      <Typography variant='body2' style={{fontWeight:'bold',color:fg,marginTop:"12px",boxShadow: "0px 2px 2px rgba(0, 0, 0, 0.25)"}}>{title}</Typography>
      <Spacer space={2}/>
      {
        shops.map((shop, index) => {
          return <ShopThumbnail key={shop.id} shop={shop} showDistance={true} />
        })
      }
      <Button
          style={{backgroundColor:fg, color:bg}}
          disabled={isLoadingMore || isReachingEnd}
          onClick={() => setSize(size+1)}
          variant='contained'
          fullWidth
      >
        {
          isLoadingMore
            ? "Loading..."
            : isReachingEnd
            ? "No more shops"
            : "Show More"
        }
      </Button>
    </Grid>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:48:01