Next.js 14中如何避免SWR首次渲染时数据为undefined?
在Next.js 14中实现首屏渲染时获取数据(替代getServerSideProps)
你的核心需求是在首屏渲染时就拿到数据,避免undefined,对应旧版本的getServerSideProps效果。在Next.js 14的App Router中,最直接的方案是利用Server Component预取数据,再传递给需要交互的Client Component,下面是具体实现:
方案1:Server Component预取数据,传递给Client Component
因为你的Home组件用到了useState处理弹窗状态,必须标记为"use client",所以我们将数据获取逻辑放在默认的Server Component(app/page.js)中,再把数据作为props传给Home组件。
步骤1:修改app/page.js(Server Component)
// app/page.js - 默认是Server Component,无需额外标记 import Home from "./Home"; export default async function Page() { // 服务端发起请求,首屏渲染时直接完成数据获取 const res = await fetch("/api/get", { cache: "no-store" // 每次请求都获取最新数据,等价于getServerSideProps的动态效果 }); if (!res.ok) { throw new Error("获取任务列表失败"); } const initialData = await res.json(); return <Home initialData={initialData} />; }
步骤2:修改Home组件(Client Component)
接收Server Component传来的初始数据,传递给SWR作为 fallback 值:
"use client"; import { useState } from "react"; import ListTasks from "@/components/ListTasks/ListTasks"; import Modal from "@/components/Modal/Modal"; import useGetData from "@/hooks/useGetData"; export default function Home({ initialData }) { const [modalProps, setModalProps] = useState({ isOpen: false, type: "", }); // 传入服务端预取的初始数据,首渲染时data不会是undefined const data = useGetData(initialData); return ( <div className="bg-slate-500 w-screen h-screen flex justify-center items-center"> {modalProps.isOpen && ( <Modal modalProps={modalProps} setModalProps={setModalProps} /> )} <div className="bg-gray-400 w-1/3 h-3/4 rounded"> <p className="text-white text-center text-2xl font-bold">To-do App</p> <div className="w-10 h-10 bg-black rounded flex justify-center items-center cursor-pointer"> <p className="text-white text-6xl pb-2" onClick={() => setModalProps({ ...modalProps, isOpen: true, type: "post" }) } > + </p> </div> <div className="bg-red-300 indent-5 rounded m-3 py-1"> <ListTasks modalProps={modalProps} setModalProps={setModalProps} tasks={data} /> </div> </div> </div> ); }
步骤3:修改useGetData钩子
支持接收初始数据作为SWR的 fallback 值:
import useSWR from "swr"; export default function useGetData(initialData) { const fetcher = (...args) => fetch(...args).then((res) => res.json()); const { data } = useSWR("/api/get", fetcher, { fallbackData: initialData, // 首渲染直接用服务端传来的数据 }); return data; }
额外说明
- 如果你的数据是静态的(不需要每次请求更新),可以去掉
{ cache: "no-store" },Next.js会自动缓存数据,实现类似getStaticProps的效果。 - 服务端fetch不会有跨域问题,因为请求是在服务器内部发起的。
- SWR会在客户端后台自动重新验证数据,保证数据新鲜度。
内容的提问来源于stack exchange,提问作者Ozan
相关产品推荐
相关产品推荐

