发布于 2026-01-06 0 阅读
0

Next.js DEV 的 SWR + 动态路由全球展示挑战赛,由 Mux 呈现:展示你的项目!

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>
}
Enter fullscreen mode Exit fullscreen mode

/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> 
}
Enter fullscreen mode Exit fullscreen mode

如果你用一个随机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>
Enter fullscreen mode Exit fullscreen mode

但随后出现了错误信息——显然出了问题,我的组件无法获取用户信息。这是怎么回事?查看网络选项卡后,我发现 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>
Enter fullscreen mode Exit fullscreen mode

这样,我们的页面现在首先会进行渲染Loading...,一旦水合过程完成,它就会获取用户数据并渲染个人资料。

希望我的解释能对您有所帮助!

文章来源:https://dev.to/wh1zk1d/swr-dynamic-routes-in-next-js-3cbl