全文共2355字,預計學習時長12分鐘
圖源:unsplash
在過去的幾個月裏,我一直在開發Next JS應用程序。應用程序使用axiosto進行API調用,然後用unstated next作爲狀態解決方案。
有很多API調用,我們不希望用戶體驗太多加載屏幕。因此,我們將axios調用的結果存儲在未聲明的存儲中。但我們遇到了一個問題,商店本身變得越來越複雜。這是有些頁面依賴於幾個API調用,有些API調用依賴於其他API調用的結果。
一週一週地過去,一些不知名的存儲變得越來越笨重。我們開始遇到奇怪錯誤,出現了我們自制的緩存邏輯難以處理罕見的邊緣情況。一定有更好的辦法。沒錯,確實有,恰巧它就是由Vercel——Next JS的創造者製作的。
Enter SWR
SWR的名字來自stale-while-revalidate,是一種在前端領域越來越流行的緩存策略。它能夠立即加載緩存的內容,同時刷新該內容,以便提供更新的內容。
對我們來說,這是性能和用戶體驗之間的完美權衡。
useSWR —如何使用它?
圖源:unsplash
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):更改緩存數據的函數
圖源:pixabay
來看一個更復雜的例子,它使用了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甚至會重新驗證並替換爲後臺的最新數據。
爲什麼需要庫?
圖源:unsplash
你可以問問自己這個問題。應用程序中可能已經有了狀態解決方案,但你無法感受到使用第三方庫進行數據獲取和緩存這樣看似簡單的操作的價值。
緩存數據是很困難的。而且隨着應用程序越來越大,它只會變得越來越難。你將遇到邊緣案例,遇到複雜的存儲和提供商,這些存儲和提供商很難理解也很難維護,漏洞也會不知道從哪兒突然冒出來。
正如菲爾·卡爾頓所說:計算機科學中只有兩件難事,緩存失效和命名問題。
與其推出自己的數據獲取解決方案,爲什麼不依賴React生態系統中最受尊敬的公司之一構建的經過實戰測試的解決方案呢?
useSWR對我們有什麼用?
將應用程序遷移到使用useSWR進行數據獲取給了我們許多好處:
1. 它能使我們刪除代碼。我最喜歡打開的請求是刪除代碼而不是添加代碼。應用程序中的代碼越少,出現錯誤的機會就越少。隨着年齡的增長,我開始越來越欣賞簡單。它允許我們刪除整個未聲明的存儲,使應用程序更簡單、更容易理解。
2. 感知性能有所提高。這個應用看起來和感覺都很快。用戶對此表示讚賞,反饋也很好。
3. 它使新開發人員更容易加入到項目中。useSWR和大多數開源項目一樣,有很好的文檔。推出我們自己的解決方案意味着我們需要編寫文檔,並教會項目新手如何處理數據獲取。用了SWR,就不必這樣做了。
圖源:unsplash
4. 它能夠變難爲易。我們的應用程序和其他大多數應用程序一樣,有很多API調用。其中一些API調用依賴於其他API調用的結果。使用useSWR,很容易編寫依賴獲取的hooks。
5. 它刷新陳舊的數據。useSWR在焦點上刷新過時的數據。這意味着用戶總能擁有最新版本的數據,不需要加載時間。
useSWR對應用程序產生了巨大的影響,它簡化了代碼,改善了用戶體驗。我的TOP 1喜歡的React庫,必須推薦給你。
一起分享AI學習與發展的乾貨
歡迎關注全平臺AI垂類自媒體 “讀芯術”
(添加小編微信:dxsxbb,加入讀者圈,一起討論最新鮮的人工智能科技哦~)