分页切换时骨架屏不显示及页面切换延迟问题排查
解决方案
问题1:分页切换无PLPSkeleton骨架屏显示
服务端组件(SC)在query参数变化时,Next.js会默认等待数据加载完成后才渲染新内容,无法直接在SC内实现加载状态,可通过以下两种方式解决:
方式1:利用路由段loading.js
在app/category目录下创建客户端组件loading.js,作为该路由的加载占位符:
// app/category/loading.js 'use client'; import PLPSkeleton from '@/components/PLPSkeleton'; export default function CategoryLoading() { return <PLPSkeleton />; }
当分页query变化触发服务端组件重新获取数据时,Next.js会自动渲染loading.js内容,直到数据加载完成。
方式2:客户端组件包裹分页与列表
将分页组件和商品列表外层改为客户端组件,借助useRouter的isPending状态控制骨架屏显示:
// app/category/ProductListWrapper.jsx 'use client'; import { useRouter, useSearchParams } from 'next/navigation'; import PLPSkeleton from '@/components/PLPSkeleton'; import ProductList from './ProductList'; // 原服务端组件提取的商品列表部分 export default function ProductListWrapper() { const router = useRouter(); const searchParams = useSearchParams(); const currentPage = searchParams.get('page') || '1'; if (router.isPending) { return <PLPSkeleton />; } return <ProductList page={currentPage} />; }
随后在app/category/page.js中引入该客户端组件:
// app/category/page.js import ProductListWrapper from './ProductListWrapper'; export default async function CategoryPage({ searchParams }) { return <ProductListWrapper />; }
问题2:分页切换URL更新延迟
当前问题源于服务端组件的导航逻辑等待API请求完成后才更新URL,需改为客户端侧触发路由跳转,先更新URL再加载数据:
修改分页组件为客户端组件
确保分页按钮在客户端组件中,使用useRouter的push方法直接跳转,无需等待API响应:
// components/Pagination.jsx 'use client'; import { useRouter, useSearchParams } from 'next/navigation'; export default function Pagination({ totalPages }) { const router = useRouter(); const searchParams = useSearchParams(); const currentPage = parseInt(searchParams.get('page') || '1'); const handlePageChange = (page) => { if (page < 1 || page > totalPages) return; const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set('page', page.toString()); router.push(`?${newSearchParams.toString()}`); }; return ( <div className="pagination"> {Array.from({ length: totalPages }, (_, i) => i + 1).map(page => ( <button key={page} onClick={() => handlePageChange(page)} className={currentPage === page ? 'active' : ''} > {page} </button> ))} </div> ); }
点击分页按钮时URL会立即更新,同时触发服务端组件重新获取对应页数据,结合骨架屏方案即可实现先更新URL再显示加载状态的效果。
配套服务端组件调整
确保服务端组件能根据searchParams的page参数调用接口:
// app/category/ProductList.jsx(服务端组件) import { getCategoryProducts } from '@/api/products'; export default async function ProductList({ page }) { const products = await getCategoryProducts({ page: parseInt(page) }); return ( <div className="product-list"> {products.map(product => ( <div key={product.id} className="product-card"> {/* 商品内容 */} </div> ))} </div> ); }
内容的提问来源于stack exchange,提问作者Abhishek kamal
相关产品推荐
相关产品推荐

