在Next.js中用useSWR处理数据的获取

2,793 阅读5分钟

数据获取模式是每个网络框架的一个非常重要的部分。这就是为什么每个网络技术的这一部分都在不断地改进和创新。

鉴于现代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 。如果你检查一下,我们应该像这样在该端口上线项目。

Welcome to Next.js Page

很好,我们已经成功建立了一个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 钩子接受两个参数并返回两个值(基于请求的状态)。它接受。

  • Akey - 一个字符串,作为我们正在获取的数据的唯一标识符。这通常是我们正在调用的API URL
  • Afetcher - 任何返回获取的数据的异步函数。

它返回。

  • 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"],
  },
};

现在,当你在浏览器上检查时,我们应该看到我们的用户如期显示出来。

Random User Generator Next.js

有了!我们有了我们的用户。所以,我们的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博客上。