在使用了一段时间的 swr 后,它已经加入了“我的最爱”工具库了😂
下面结合我的个人经验,谈谈为什么你应该使用它。
在请求接口的时候,一般都需要维护请求的状态。比如加载列表的时候,通常都需要区分下 loading、empty、success、error 等状态,然后更新相关的视图,看上去就是下面的代码
const [data, setData] = useState([]);const [loading, setLoading] = useState(false);const [error, setError] = useState(null);// more states...const sendRequest = useCallback(() => {setLoading(true);fetchData().then(data => {setLoading(false);setData(data);setError(null);}).catch(err => {setLoading(false);setError(err);setData(null);});}, []);
上面的代码缺陷很多:首先是模板代码多,维护麻烦;第二是容易出错,比如忘记重置相关变量、没考虑竞争等等问题。
而 swr 里面就几行代码:
const fetcher = (url) => fetch(url).then(res => res.json());// useSwr(apiKey, fetcher, options)const { data, isValidating, error } = useSwr('/api/list', fetcher);
注意:
swr 在发起请求的时候,会优先使用缓存的数据,然后当请求返回的时候更新视图。
为什么这个功能很重要呢?还是用上面那个列表接口作为例子,当用户第二次请求接口的时候(比如从某个页面返回),直接就能看到列表里的数据,然后过一会刷新成最新数据,在体验上就感觉很流畅。
如果某个接口更新不是很频繁,那么第二次请求的结果还是原来的数据,用户根本感觉不到有请求的过程,这就很爽😄。
还有个额外的好处,当用户返回之前的页面时,浏览器还能保留滚动位置。
当一个请求依赖另一个请求的时候,常规做法是在请求后接另一个请求,这样写起来很复杂。
而 swr 用了一种很巧妙的方法,当参数抛出异常或者返回 false 值,就不会请求。这种写法省了不少功夫!!
const { data: user } = useSWR('/api/user')// useSwr(apiKey, fetcher, options)// apiKey 可以是函数const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
原理是当请求里面的函数抛错的时候,就不会继续请求。
这两个场景覆盖了中后台很大的代码(CRUD BOY你懂的),这里官方有例子我不再赘述了。
可以用 useSWRImmutable
来请求不变的数据(比如 select 选项),来避免重复请求。
swr 虽然是个用于数据请求的库,但是没有限制 fetcher 的具体实现,他可以是任意返回 promise 的函数。
可以用它来管理全局状态,不管是本地的或者远程的。