useSWRInfinite的getKey函数pageIndex始终为1的问题求助
问题原因
你代码里的核心问题出在getKey函数的定义上,共3处错误:
- 参数定义错误
useSWRInfinite只会给getKey传递两个参数:pageIndex(当前页索引,从0开始计数)、previousPageData(上一页接口返回的数据)。你额外声明的第三个形参category是不存在的,实际取值为undefined,导致生成的分页key重复,SWR会认为你一直请求同一页数据,所以pageIndex不会增长。 - 终止条件和你的接口返回结构不匹配
从你后续处理数据的写法data ? [].concat(...data) : []可以看出,你的getNearbyShops接口直接返回店铺数组,你写的终止判断if (previousPageData && !previousPageData.data) return null中的.data字段根本不存在,该条件永远不会生效。 - 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
相关产品推荐
相关产品推荐

