使用Next.js + SWR实现实时数据展示失败求助
Next.js + SWR SSR示例页面无法显示数据的解决方案
问题场景
开发实时数据展示项目时,采用Next.js和SWR技术,复制SWR官网的SSR示例代码后页面无法显示数据。通过npx create-next-app --example hello-world hello-world-app创建新项目,粘贴代码后无任何效果。相关代码如下:
package.json
{ "name": "swr-ssr", "version": "1.0.0", "scripts": { "dev": "next", "build": "next build", "start": "next start", "post-update": "yarn upgrade --latest" }, "dependencies": { "next": "latest", "react": "18.2.0", "react-dom": "18.2.0", "swr": "2.0.0" }, "license": "MIT", "keywords": [], "description": "" }
index.js
import useSWR, { SWRConfig } from "swr"; const fetcher = (url) => fetch(url).then((res) => res.json()); const API = "https://api.github.com/repos/vercel/swr"; export async function getServerSideProps() { const repoInfo = await fetcher(API); return { props: { fallback: { [API]: repoInfo } } }; } function Repo() { const { data, error } = useSWR(API); console.log("Is data ready?", !!data); if (error) return "An error has occurred."; if (!data) return "Loading..."; return ( <div> <h1>{data.name}</h1> <p>{data.description}</p> <strong>👀 {data.subscribers_count}</strong>{" "} <strong>✨ {data.stargazers_count}</strong>{" "} <strong>🍴 {data.forks_count}</strong> </div> ); } export default function App({ fallback }) { return ( <SWRConfig value={{ fallback }}> <Repo /> </SWRConfig> ); }
问题根源
你使用的是Next.js 13+版本,该版本默认启用App Router,但你复制的SWR SSR示例是基于旧版的Pages Router编写的。getServerSideProps是Pages Router特有的服务端渲染方法,在App Router中不会被执行,导致SWR无法获取到预加载的fallback数据,页面一直停留在加载状态。
两种解决办法
办法一:切换到Pages Router模式
- 在项目根目录创建
pages文件夹,将你的index.js移动到pages/index.js路径下 - 删除项目默认生成的
app文件夹 - 重启开发服务器(
npm run dev),Next.js会自动切换到Pages Router模式,此时getServerSideProps会正常执行,页面就能显示数据了。
办法二:适配App Router写法(推荐)
App Router中推荐使用Server Components获取初始数据,再传递给客户端组件配合SWR使用。修改代码如下(替换默认的app/page.js):
'use client' import useSWR, { SWRConfig } from 'swr' const fetcher = (url) => fetch(url).then(res => res.json()) const API = 'https://api.github.com/repos/vercel/swr' // 服务器组件中获取初始数据 async function getInitialData() { const res = await fetch(API) return res.json() } export default async function Page() { const initialData = await getInitialData() return ( <SWRConfig value={{ fallback: { [API]: initialData } }}> <Repo /> </SWRConfig> ) } function Repo() { const { data, error } = useSWR(API, fetcher) if (error) return 'An error has occurred.' if (!data) return 'Loading...' return ( <div> <h1>{data.name}</h1> <p>{data.description}</p> <strong>👀 {data.subscribers_count}</strong> {' '} <strong>✨ {data.stargazers_count}</strong> {' '} <strong>🍴 {data.forks_count}</strong> </div> ) }
额外排查点
- 打开浏览器控制台,检查是否有网络请求报错(GitHub API支持跨域,大概率不会出现CORS问题)
- 若使用Pages Router,可在
getServerSideProps中添加console.log(repoInfo),查看服务端是否成功获取到数据,验证函数是否执行。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

