swr,解决 React 项目 API 调用的最好方案

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swr,解决 React 项目 API 调用的最好方案相关的知识,希望对你有一定的参考价值。

swr,解决 React 项目 API 调用的最好方案

搜了一圈,感觉 swr 源码学习的文章不少,但是好像使用方面的确实有限,所以……

目前体感是觉得使用 swr 会比 redux-saga 要舒服一些,首先代码量小很多,其次同步异步方面的操作也更加简洁明了。swr 对各种 API 调用的支持也很好,官方文档还有包括 Axios 和 GraphQL 的配置,总体来说应该是最近使用的一些包中,最能够解决 React 项目中 API 调用的库了。

swr 是 stale-while-revalidate 的缩写,stale 就是放置很久的意思,具体怎么翻译我也不是很清楚,大概就是 状态被放置不变,但是还会重新验证 的感觉。这是一个 nextjs 团队开发的 node 包,其作用包括当 fetch API 使用和控制管理状态同步。

其本身是一个 React Hooks,因此搭配 React 生态圈使用会比较好(如 Next 系列),其余框架没有尝试过,这里不做妄言。

fetch API

参考代码如下:

import React,  useState, useEffect  from "react";
import useSWR from "swr";

const fetcher = (...args) => fetch(...args).then((res) => res.json());

const SWR = () => 
  const [products, setProducts] = useState(null);

  const  data, error  = useSWR(
    "https://dummyjson.com/products?limit=10",
    fetcher
  );

  useEffect(() => 
    if (data) 
      setProducts(data.products);
    
  , [data]);

  if (error) 
    return <p>Error</p>;
  

  if (!products) 
    return <p>loading</p>;
  

  return (
    <div>
      products.map((product) => 
        return (
          <div key=product.id>
            <h1>product.title</h1>
            <p>product.description</p>
          </div>
        );
      )
    </div>
  );
;

export default SWR;

显示效果如下:

useSWR 是 swr 封装的 hooks,使用这个 hooks 可以轻松的获取 dataerror 两个属性,从而进行操作。如果 swr 只能提供这些功能的话,那么自己封装一个 custom hook 也一样,为什么非要使用 swr?

串行调用

参考以下的代码:

import React,  useState, useEffect  from "react";
import useSWR from "swr";

const fetcher = (...args) => fetch(...args).then((res) => res.json());

console.time("fetching");

const SWR = () => 
  const  data: products, error  = useSWR(
    "https://dummyjson.com/products?limit=1",
    fetcher
  );

  const  data: productDetail, error: productError  = useSWR(
    () => `https://dummyjson.com/products/$products.products[0].id`,
    fetcher
  );

  console.log(productDetail);

  if (!productDetail) 
    return <p>Loading</p>;
  

  console.timeLog("fetching");

  return (
    <div>
      <h1>productDetail.title</h1>
      <p>productDetail.description</p>
    </div>
  );
;

export default SWR;

渲染结果如下:

从抓取数据到成功用了 8000ms,并且,数据是可以成功渲染出来的。也就是说,swr 实现了从 /products 这个 API 中获取到了产品,随后再使用获取的产品 id 去调用产品详情这样的操作。没有多余的代码,仅仅在使用 useSWR 中再调用了一个匿名函数,就完成了这样一个套用很多 thenable 的代码。

代码量:2 行。

并行调用

swr 默认情况下是支持并联操作的,参考以下代码:

import React,  useState, useEffect  from "react";
import useSWR from "swr";

const fetcher = (...args) => fetch(...args).then((res) => res.json());

console.time("fetching");

const SWR = () => 
  const  data: product1, error: err1  = useSWR(
    "https://dummyjson.com/products/1",
    fetcher
  );
  const  data: product2, error: err2  = useSWR(
    "https://dummyjson.com/products/2",
    fetcher
  );
  const  data: product3, error: err3  = useSWR(
    "https://dummyjson.com/products/3",
    fetcher
  );

  if (!product1 || !product2 || !product3) 
    return <p>Loading</p>;
  

  console.log(product1);
  console.log(product2);
  console.log(product3);

  console.timeLog("fetching");

  return (
    <div>
      <h1>product1.title</h1>
      <p>product1.description</p>
    </div>
  );
;

export default SWR;

获取时间如下:

并且数据是直接从 https://dummyjson.com/products 抓下来的,而非 local cache。这也能看出来,这几个请求是同时发布,也就是并行进行的。

光是这几个功能,就已经体现出了 swr 与其他第三方库的优势,更不用说除了单纯的 API 调用外,swr 还具有状态管理的功能。

管理状态

以下是来自官方文档的截图:

swr 还带有状态管理的方式,即 在失去焦点后 -> 重新获得焦点 这个过程中,swr 会重新验证状态。

在上面的案例中,这就代表着 API 会再一次被调用,当然,因为这是一个静态 API,所以会返回一个 304 让浏览器从缓存中调取数据。

除了在 onFocus 的时候重新更新状态外(默认开启),swr 还有通过时间间隔更新状态,重新连接时更新状态(默认开启)这两个选择,通过合理搭配合适的选项,我们也能更加轻松的实现原本代码量不小的功能。

其他功能

swr 还可以轻松实现分页功能(pagination),它可以监听到状态的变化后重新调用 API,更新数据。

这种功能搭配上 预加载(prefetching),可以轻松实现让页面的即时跳转功能。

除了上面提到的几个功能外,swr 还有 mutation, suspense 等功能说明,不过鉴于我还没玩到 React 的 suspense,并且暂时还没有折腾配置的需求,所以这里就不多赘述。

同样,swr 作为 Next.js 生态圈的一部分,它也有针对 Next.js 的 SSR 和 SSG 进行支持,这也是下一步会要认真挖掘的特性。

以上是关于swr,解决 React 项目 API 调用的最好方案的主要内容,如果未能解决你的问题,请参考以下文章

浏览器可以直接调用react项目里的代码接口吗

在同构的 Redux 应用程序中,最好的做法是保持 API 调用较小,还是一次性发送所有信息?

vu-query: 目前vue3最好用的请求缓存库

CORS 阻止来自 Dockerized React 项目的 API 调用

React Native - 同步调用restful API

SWR 根据下拉列表中的选定值获取数据