全文共2355字,预计学习时长12分钟
在过去的几个月里,我一直在开发Next JS应用程序。应用程序使用axiosto进行API调用,然后用unstated next作为状态解决方案。
有很多API调用,我们不希望用户体验太多加载屏幕。因此,我们将axios调用的结果存储在未声明的存储中。但我们遇到了一个问题,商店本身变得越来越复杂。这是有些页面依赖于几个API调用,有些API调用依赖于其他API调用的结果。
一周一周地过去,一些不知名的存储变得越来越笨重。我们开始遇到奇怪错误,出现了我们自制的缓存逻辑难以处理罕见的边缘情况。一定有更好的办法。没错,确实有,恰巧它就是由Vercel——Next JS的创造者制作的。
Enter SWR
SWR的名字来自stale-while-revalidate,是一种在前端领域越来越流行的缓存策略。它能够立即加载缓存的内容,同时刷新该内容,以便提供更新的内容。
对我们来说,这是性能和用户体验之间的完美权衡。
useSWR —如何使用它?
useSWR是一个由Vercel制作的React Hook库。它从API或其他外部源获取数据,然后将数据保存在缓存中,并呈现数据。先来看一个React组件的示例,该组件从JSON服务器获取todo列表并呈现它们:
import React from"react";
import "./App.css";const todosEndpoint = "http://localhost:3001/todos";const TodoApp = () =>{
const [todos, setTodos] =React.useState([]); React.useEffect(()=> {
const getData = async () => {
const response = awaitfetch(todosEndpoint);
const data = await response.json();
setTodos(data);
}; getData();
}, []); return (
<div className="App">
{todos.map((todo) => (
<div key={todo.id}>{todo.title}</div>
))}
</div>
);
};export default TodoApp;
接下来看看同一个组件,这次重构为useswr:
import React from"react";
import useSWR from "swr";const todosEndpoint = "http://localhost:3001/todos";const getData = async ()=> {
const response = awaitfetch(todosEndpoint);
return await response.json();
};const TodoApp = () => {
const { data: todos } =useSWR(todosEndpoint, getData);
return (
<div>
{todos && todos.map(todo=> (
<divkey={todo.id}>{todo.title}</div>
)}
</div>
);
};export default TodoApp;
如你所见,它看起来与前面的实现非常相似。
本例中使用useSWR(key,fetcher,options)来获取todo列表。useSWR使用该密钥进行缓存,例子中使用了todos端点。对于fetcher,传入了一个异步函数来获取todo列表。
需要注意的是,useSWR对于如何获取数据是不敏感的。你可以使用任何你喜欢的异步数据获取策略,可以使用fetch、axios甚至GraphQL。只要函数异步返回数据,useSWR就没问题。
调用useSWR将返回以下参数:
· data:由获取程序解析的给定密钥的数据(如果尚未加载,则未定义)
· error:取数器抛出的错误
· isvaliding:boolean表示是否有正在进行的请求或重新验证
· mutate(data?,shouldRevalidate):更改缓存数据的函数
来看一个更复杂的例子,它使用了useSWR返回的更多参数。在本例中获取一个todo,并呈现一个复选框来切换todo的完成状态。单击复选框时,发出一个PUT请求来更新todo,并调用mutate来更新useSWR的缓存。
import React from"react";
import useSWR from "swr";
import "./App.css";const todosEndpoint = "http://localhost:3001/todos";const getTodo = async(id) => {
const response = awaitfetch(`${todosEndpoint}/${id}`);
return await response.json();
};const updateTodo = async (id, todo) => {
const response = awaitfetch(`${todosEndpoint}/${id}`, {
method: "PUT",
headers: {
"Content-type":"application/json; charset=UTF-8",
},
body: JSON.stringify(todo),
});
return await response.json();
};const TodoApp = () => {
const todoId = 1;
const key =`${todosEndpoint}/${todoId}`; const {data: todo, mutate } = useSWR(key, () =>
getTodo(todoId)
); const toggleCompleted = async () => {
const newTodo = {
...todo,
completed: !todo.completed,
};
await updateTodo(todoId, newTodo);
mutate(newTodo);
}; if (!todo) {
return<div>Loading...</div>;
} return (
<div>
<p>{todo.title}</p>
<div>
<input
type="checkbox"
id="completed"
name="completed"
value="completed"
checked={todo.completed}
onChange={toggleCompleted}
/>
<labelhtmlFor="completed">Completed</label>
</div>
</div>
);
};export default TodoApp;
使用mutate是提高web应用程序感知性能的一个好方法,可以对数据应用本地更改并更新视图,而无需等待远程数据源更新。useSWR甚至会重新验证并替换为后台的最新数据。
为什么需要库?
你可以问问自己这个问题。应用程序中可能已经有了状态解决方案,但你无法感受到使用第三方库进行数据获取和缓存这样看似简单的操作的价值。
缓存数据是很困难的。而且随着应用程序越来越大,它只会变得越来越难。你将遇到边缘案例,遇到复杂的存储和提供商,这些存储和提供商很难理解也很难维护,漏洞也会不知道从哪儿突然冒出来。
正如菲尔·卡尔顿所说:计算机科学中只有两件难事,缓存失效和命名问题。
与其推出自己的数据获取解决方案,为什么不依赖React生态系统中最受尊敬的公司之一构建的经过实战测试的解决方案呢?
useSWR对我们有什么用?
将应用程序迁移到使用useSWR进行数据获取给了我们许多好处:
1. 它能使我们删除代码。我最喜欢打开的请求是删除代码而不是添加代码。应用程序中的代码越少,出现错误的机会就越少。随着年龄的增长,我开始越来越欣赏简单。它允许我们删除整个未声明的存储,使应用程序更简单、更容易理解。
2. 感知性能有所提高。这个应用看起来和感觉都很快。用户对此表示赞赏,反馈也很好。
3. 它使新开发人员更容易加入到项目中。useSWR和大多数开源项目一样,有很好的文档。推出我们自己的解决方案意味着我们需要编写文档,并教会项目新手如何处理数据获取。用了SWR,就不必这样做了。
4. 它能够变难为易。我们的应用程序和其他大多数应用程序一样,有很多API调用。其中一些API调用依赖于其他API调用的结果。使用useSWR,很容易编写依赖获取的hooks。
5. 它刷新陈旧的数据。useSWR在焦点上刷新过时的数据。这意味着用户总能拥有最新版本的数据,不需要加载时间。
useSWR对应用程序产生了巨大的影响,它简化了代码,改善了用户体验。我的TOP 1喜欢的React库,必须推荐给你。
留言点赞关注
我们一起分享AI学习与发展的干货
编译组:安然
相关链接:https://medium.com/frontend-digest/useswr-my-new-favorite-react-library-cd87a914a5b1
如转载,请私信小芯,遵守转载规范