Next.js静态站点中getStaticProps分页参数添加失败的解决问询
静态站点下Next.js + GraphQL分页实现方案
由于你需要构建静态站点,无法使用getServerSideProps,推荐采用客户端动态查询的方式实现分页,核心思路是:构建时通过getStaticProps生成第一页的静态内容,后续分页数据在客户端通过数据请求工具动态获取,既满足静态站点的构建要求,又能实现动态分页功能。下面给出两种实用方案:
方案一:使用SWR实现客户端数据获取与缓存
SWR是Next.js官方推荐的数据请求库,自带缓存、重验证等特性,非常适合静态站点的动态数据需求。
步骤1:安装依赖
npm install swr
步骤2:封装GraphQL请求函数
async function fetchCharacters(page) { const res = await fetch('https://rickandmortyapi.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: ` query GetCharacters($page: Int) { characters(page: $page) { results { id name status species } info { pages next prev } } } `, variables: { page } }) }); const data = await res.json(); return data.data; }
步骤3:改造页面组件
import { useState } from 'react'; import useSWR from 'swr'; // 构建时预获取第一页数据,作为静态内容的一部分 export async function getStaticProps() { const initialData = await fetchCharacters(1); return { props: { initialData } }; } export default function CharactersPage({ initialData }) { const [currentPage, setCurrentPage] = useState(1); // 用SWR根据当前页码动态请求数据,复用初始数据避免重复请求 const { data, error, isLoading } = useSWR( [currentPage], () => fetchCharacters(currentPage), { initialData } ); if (error) return <div>加载失败,请稍后重试</div>; if (isLoading && !data) return <div>加载中...</div>; const { characters } = data; return ( <div> <table border="1" cellPadding="8"> <thead> <tr> <th>ID</th> <th>角色名</th> <th>状态</th> <th>物种</th> </tr> </thead> <tbody> {characters.results.map(char => ( <tr key={char.id}> <td>{char.id}</td> <td>{char.name}</td> <td>{char.status}</td> <td>{char.species}</td> </tr> ))} </tbody> </table> <div style={{ marginTop: '20px', display: 'flex', gap: '10px', alignItems: 'center' }}> <button onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))} disabled={currentPage === 1} > 上一页 </button> <span>第 {currentPage} 页 / 共 {characters.info.pages} 页</span> <button onClick={() => setCurrentPage(prev => Math.min(prev + 1, characters.info.pages))} disabled={currentPage === characters.info.pages} > 下一页 </button> </div> </div> ); }
方案二:使用Apollo Client实现客户端查询
如果你的项目已经在使用Apollo Client,可以用它来实现动态分页:
步骤1:配置Apollo Client
在项目中创建apollo-client.js:
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; const httpLink = createHttpLink({ uri: 'https://rickandmortyapi.com/graphql', }); export const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache(), });
步骤2:在页面中使用Apollo Client
import { useState } from 'react'; import { useQuery, gql } from '@apollo/client'; import { client } from '../apollo-client'; const GET_CHARACTERS = gql` query GetCharacters($page: Int) { characters(page: $page) { results { id name status species } info { pages next prev } } } `; export async function getStaticProps() { const { data } = await client.query({ query: GET_CHARACTERS, variables: { page: 1 } }); return { props: { initialData: data } }; } export default function CharactersPage({ initialData }) { const [currentPage, setCurrentPage] = useState(1); const { loading, error, data } = useQuery(GET_CHARACTERS, { variables: { page: currentPage }, initialData }); if (error) return <div>加载失败</div>; if (loading && !data) return <div>加载中...</div>; const { characters } = data; // 分页按钮和表格渲染逻辑同方案一 return ( <div> {/* 表格代码 */} {/* 分页按钮代码 */} </div> ); }
关键注意事项
- 避免Hydration不匹配:通过
getStaticProps预取的第一页数据,要作为客户端请求工具的初始数据传入,保证服务端渲染内容和客户端初始化内容一致。 - 状态管理:用React状态
currentPage控制当前页码,点击分页按钮时更新状态,触发数据重新请求。 - 错误与加载状态:必须处理数据请求中的加载、错误场景,提升用户体验。
- SEO兼容性:静态生成的第一页内容完全支持SEO,客户端渲染的后续页内容,现代搜索引擎也能正常抓取解析,如果有极高SEO需求,可以考虑预生成所有页面(但灵活性较差)。
内容的提问来源于stack exchange,提问作者ChristianOConnor
相关产品推荐
相关产品推荐

