Next.js 中的 SWR + 动态路由
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
嘿,各位!
如果你最近在 Next.js 中使用过客户端数据获取,你可能听说过SWR。它自带useSWR一个 React hook,可以将客户端数据获取中所有复杂的操作(缓存、重新验证、焦点跟踪等)变得非常简单。
只需几行代码即可实现:
// Import the hook
import useSWR from 'swr'
// Define a custom fetcher function
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
// Use the hook to fetch your data
const { data, error } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
/api/user很简单,对吧?当你尝试获取一个不带查询参数的端点时useSWR,确实很简单,比如 `$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$(1$((1 '$((1 '$((1 '$((1 '$(( '$( '$( '$( '$(1$( '$(1$( '$(1$( '$(1 '$(1$( '$(1$( '$(1$( '$(1 '$(1$(1$( '$(1$( '$(1 1 '$(1$(1$(1 1$(1$(1$(1 1$(1$(1$(1 1$(1$(1$(1. 1$(1$(1$( 1 1$(1$(1$(1. .... 1$(1$(1. 1$(1$(1$(1. 1$(1$(1. 1$(1$(1. 1$(1$(1. 1$(1$(1. 1$(1$(1. 1$(1$(1. 1$(1$(1. 1
假设我们有一个动态用户路由/pages/user/[id].js,它应该根据我们作为路由参数传递的 ID 显示用户个人资料。
访问该 ID 参数的代码如下所示:
// Import the useRouter hook from Next.js
import { useRouter } from 'next/router'
function Profile() {
// Use the useRouter hook
const router = useRouter()
// Grab our ID parameter
const { id } = router.query
return <div>user id: {id}</div>
}
如果你用一个随机ID(http://localhost:3000/user/42例如)打开该页面,你应该会在渲染后的页面上看到这个ID(user id: 42)。现在,我们不只是渲染这个ID,而是从我们的API端点获取与该ID关联的用户,并渲染一个个人资料页面。
我当时尝试这样做的时候,以为只要把 ID 参数传递给useSWR钩子函数,就能轻松创建一个漂亮的个人资料页面。代码如下:
import useSWR from 'swr'
import { useRouter } from 'next/router'
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
const router = useRouter()
const { id } = router.query
const { data, error } = useSWR(`/api/user/${id}`, fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
但随后出现了错误信息——显然出了问题,我的组件无法获取用户信息。这是怎么回事?查看网络选项卡后,我发现 ID 参数没有传递给 fetch 调用——而是显示为空undefined。这是为什么呢?ID 明明就在那里,到底是怎么回事?
答案在Next.js 文档中:
使用自动静态优化进行静态优化的页面,在进行水合时不会提供路由参数,即
query不会返回一个空对象{}。水合完成后,Next.js 会触发应用程序更新,将路由参数添加到query对象中。
由于我没有在该页面上使用getServerSideProps`or` getStaticProps,Next 为其启用了自动静态优化——这意味着router.query在水合过程完成之前,`or` 中的动态参数不可用。之前,` queryor` 只是一个空对象——这就是为什么网络选项卡显示为空undefined。
那么我们如何才能确保useSWR动态路由参数准备就绪后再进行设置呢?
太长不看
import useSWR from 'swr'
import { useRouter } from 'next/router'
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
const router = useRouter()
const { id } = router.query
// Use a ternary operator to only fetch the data when the ID isn't undefined
const { data, error } = useSWR(id ? `/api/user/${id}` : null, fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
这样,我们的页面现在首先会进行渲染Loading...,一旦水合过程完成,它就会获取用户数据并渲染个人资料。
希望我的解释能对您有所帮助!
文章来源:https://dev.to/wh1zk1d/swr-dynamic-routes-in-next-js-3cbl