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 可以轻松的获取 data
和 error
两个属性,从而进行操作。如果 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 调用的最好方案的主要内容,如果未能解决你的问题,请参考以下文章
在同构的 Redux 应用程序中,最好的做法是保持 API 调用较小,还是一次性发送所有信息?
CORS 阻止来自 Dockerized React 项目的 API 调用