数据获取模式是每个网络框架的一个非常重要的部分。这就是为什么每个网络技术的这一部分都在不断地改进和创新。
鉴于现代Web开发模式在很大程度上依赖于数据获取功能,以支持像SSR和CSR这样的功能,因此紧跟网络这一领域的变化是有意义的。
在这篇文章中,我将向你介绍最近刚刚引入Next.js的useSWR
钩子,以帮助使数据获取更容易。为了做到这一点,我们将建立一个随机用户生成网站。并不是说你需要又一个这样的随机生成网站,但事实证明,它能有效地向开发者展示事物的工作原理。我的目标是确保在这篇文章的最后,你会对useSWR
钩子有更多的了解,从而用它来改善你的Next.js创作经验。在我们深入讨论之前,这里有一个关于它的简介。
useSWR
SWR在这里指的是 "stale-while-revalidate",我想Next.js的开发者已经很熟悉这个术语了。Next.js团队建立它是为了给开发者在使用Next时提供更多获取远程数据的方法。它基本上是一组React Hooks,提供了诸如重新验证、突变、缓存等开箱即用的功能。
我喜欢这样想:useSWR
为我解决的问题是,它让我有机会立即向用户展示一些东西,并在实际内容在幕后加载时,以一种方便的方式管理他们的体验。它是这样做的。
- 当一个请求被提出时,它首先返回一个缓存的值。可能是在
getStaticProps()
函数中生成的东西 - 接下来,服务器将启动一个重新验证的过程,并获取页面的实际数据。
- 最后,当重新验证成功后,SWR将用实际数据更新页面。
在这种情况下,用户就不会被困在加载屏幕上,你的网站就会保持快速和高性能。在SWR的其他好处中,你可以用它来从任何支持HTTP的服务器中检索数据,而且它有完整的TypeScript支持。让我们深入了解一下,用Next.js和useSWR
钩子来设置我们的随机用户生成器应用。
设置Next.js应用程序
要快速设置Next.js应用程序,请打开一个终端窗口,像这样运行create-next-app
命令。
npx create-next-app useswr-user-generator
按照提示完成设置过程,你应该在本地有一个useswr-user-generator
应用程序。导航到应用程序目录,用这个命令安装SWR。
cd useswr-user-generator # navigate into the project directory
npm install swr axios # install swr and axios
npm run dev # run the dev server
上面的命令将安装SWR和Axios软件包,并在你的浏览器上打开项目:localhost:3000
。如果你检查一下,我们应该像这样在该端口上线项目。
很好,我们已经成功建立了一个Next.js应用程序。让我们继续构建这个随机生成器的东西,好吗?
用SWR获取数据
在项目的根部,创建一个components
文件夹。在这个文件夹中,添加一个Users.js
文件,并用下面的代码段来更新它。
// components/Users.js
import axios from "axios";
import useSWR from "swr";
import Image from "next/image";
export default function Users() {
const address = `https://randomuser.me/api/?results=6`;
const fetcher = async (url) => await axios.get(url).then((res) => res.data);
const { data, error } = useSWR(address, fetcher);
if (error) <p>Loading failed...</p>;
if (!data) <h1>Loading...</h1>;
return (
<div>
<div className="container">
{data &&
data.results.map((item) => (
<div key={item.cell} className={`user-card ${item.gender}`}>
<div>
<Image
width={100}
height={100}
src={item.picture.large}
alt="user-avatar"
className="img"
/>
<h3>{`${item.name.first} ${item.name.last}`}</h3>
</div>
<div className="details">
<p>Country: {item.location.country}</p>
<p>State: {item.location.state}</p>
<p>Email: {item.email}</p>
<p>Phone: {item.phone}</p>
<p>Age: {item.dob.age}</p>
</div>
</div>
))}
</div>
</div>
);
}
让我们浏览一下这段代码。在上面的片段中,我们使用useSWR()
钩子来获取我们的APIaddress
变量中指定的六个用户的数据。
useSWR
钩子接受两个参数并返回两个值(基于请求的状态)。它接受。
- A
key
- 一个字符串,作为我们正在获取的数据的唯一标识符。这通常是我们正在调用的API URL - A
fetcher
- 任何返回获取的数据的异步函数。
它返回。
data
- 请求的结果(如果它是成功的)error
- 发生的错误(如果有错误)。
在其最简单的状态下,这就是如何用useSWR
来获取数据。
import useSWR from 'swr'
export defaul function Users() {
const { data, error } = useSWR('/api/users', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
在我们的例子中,我们在address
变量中保存了我们的API URL,并定义了我们的fetcher
函数来处理请求并返回响应。
N.B., useSWR
docs建议使用Next.js的本地获取函数与SWR一起工作,但对我来说不是这样的。我试过了,但不太行得通,所以我才用Axios代替。
让我们在浏览器上检查一下,看看我们是否得到了我们的用户。为了显示用户页面,让我们把<Users />
组件导入到pages/index.js
文件中,并像这样更新它。
// pages/index
import Head from "next/head";
import Users from "../components/Users";
export default function Home() {
return (
<div>
<Head>
<title>Create Next App</title>
<meta name="description" content="Random user generator" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Users />
</div>
);
}
你可能已经注意到,我在Users.js
文件中使用Next.js图像组件来显示用户的头像。因此,我们需要像这样在next.config.js
文件中指定图像域。
module.exports = {
reactStrictMode: true,
images: {
domains: ["randomuser.me"],
},
};
现在,当你在浏览器上检查时,我们应该看到我们的用户如期显示出来。
有了!我们有了我们的用户。所以,我们的useSWR
钩子正在工作!但是,就这样吗?这与其他数据获取方法有什么不同?请继续阅读...
为什么是useSWR
?
在这一点上,这是一个很有可能被问到的问题。除了声明性很强之外,我不会说这对我来说是一个巨大的改进。这可能使得现在是一个很好的时机来谈论我非常喜欢的useSWR
的一个特性(包括其他)。
分页
用useSWR
分页是一件很容易的事。让我们来举例说明:想象一下,我们不是只加载六个用户,而是希望能够生成更多的用户,并根据需要将它们添加到这个页面。当你在构建一个用户需要浏览同一内容的多个页面的应用程序时,这一点特别有帮助。我们可以通过在我们的用户页面的末尾添加一个Load More按钮来证明这一点,以便在点击时产生更多的用户。让我们更新一下索引页,将一个计数道具传递给我们的<Users />
组件。
// pages/index.js
import Head from "next/head";
import Users from "../components/Users";
export default function Home() {
const [count, setCount ] = useState(0);
return (
<div>
<Users count={count} setCount={setCount} />
</div>
);
}
接下来,让我们在components/Users.js
文件中添加一个按钮来更新计数,并从我们的API加载更多的用户到页面。
import axios from "axios";
import useSWR from "swr";
import Image from "next/image";
export default function Users({ count, setCount }) {
const address = `https://randomuser.me/api/?results=${count}`;
const fetcher = async (url) => await axios.get(url).then((res) => res.data);
const { data, error } = useSWR(address, fetcher);
if (error) <p>Loading failed...</p>;
if (!data) <h1>Loading...</h1>;
return (
<div>
<div className="container">
// show users
</div>
<center>
<div className="btn">
<button onClick={() => setCount(count + 3)}>Load More Users</button>
</div>
</center>
</div>
);
}
让我们在浏览器上检查一下,看看我们的按钮是否按预期工作。当点击时,它应该再加载三个用户,并与现有用户一起呈现在页面上。
就像一个魅力十足的工作。然而,这给我们带来了另一个问题。当按钮被点击时,Next.js将向我们的API发出一个新的请求,以获取这三个用户,这将触发我们的加载状态。这就是为什么当按钮被点击时,你会注意到屏幕上有闪烁的现象。幸运的是,我们有一个简单的解决方案,这主要归功于SWR的缓存。
我们可以预先生成那些用户(或不同上下文中的下一个页面),并在一个隐藏的<div>
元素中渲染它们。这样,当按钮被点击时,我们只需显示该元素。结果是,请求将在我们点击按钮之前发生,而不是在什么时候。
看到了吗?不再有闪烁了。
在其他方面,这里有一些你从SWR中得到的惊人的功能。
- 可重复使用的数据获取
- 内置的缓冲区
- 支持SSR/ISR/SSG
- 支持TypeScript
- 变异和重新验证
还有更多的性能优势,我们无法在这篇文章的范围内涵盖。作为下一步,我希望你能查看SWR文档以了解更多关于使用和好处的细节。
总结
在这篇文章中,我们已经了解了useSWR
钩子的基本知识。我们还用Next.js建立了一个小型的随机用户生成器应用,以展示SWR的功能。我希望这篇文章能让你对在Next.js应用程序中用useSWR
来获取数据有一定的了解。我们建立的网站的实时演示在Netlify上。如果你想根据自己的喜好进行调整,可以随时玩玩,也可以从GitHub分叉代码库。
帖子《用useSWR处理Next.js中的数据获取》首次出现在LogRocket博客上。