效能
SWR 在各種 Web 應用程式中提供關鍵功能,因此**效能**是首要考量。
SWR 內建的**快取**和**重複資料刪除**會跳過不必要的網路請求,但 useSWR
hook 本身的效能仍然很重要。在複雜的應用程式中,單一頁面渲染中可能會出現數百個 useSWR
呼叫。
SWR 確保您的應用程式具有
- 沒有不必要的請求
- 沒有不必要的重新渲染
- 沒有匯入不必要的程式碼
且無需您變更任何程式碼。
重複資料刪除
在您的應用程式中重複使用 SWR hook 是很常見的。例如,一個應用程式會渲染目前使用者的頭像 5 次
function useUser () {
return useSWR('/api/user', fetcher)
}
function Avatar () {
const { data, error } = useUser()
if (error) return <Error />
if (!data) return <Spinner />
return <img src={data.avatar_url} />
}
function App () {
return <>
<Avatar />
<Avatar />
<Avatar />
<Avatar />
<Avatar />
</>
}
每個 <Avatar>
元件內部都有一個 useSWR
hook。由於它們具有相同的 SWR key,並且幾乎同時渲染,**只會發出 1 個網路請求**。
您可以到處重複使用您的資料 hook(例如上述範例中的 useUser
),而無需擔心效能或重複的請求。
還有一個 dedupingInterval
選項,可用於覆寫預設的重複資料刪除間隔。
深度比較
SWR 預設會**深度比較**資料變更。如果 data
值沒有變更,則不會觸發重新渲染。
如果您想變更行為,也可以透過 compare
選項自訂比較函式。例如,某些 API 回應會傳回您可能想要從資料差異中排除的伺服器時間戳記。
依賴收集
useSWR
會傳回 4 個**有狀態**的值:data
、error
、isLoading
和 isValidating
,每個值都可以獨立更新。例如,如果我們在完整的資料獲取生命週期內印出這些值,它會是像這樣
function App () {
const { data, error, isLoading, isValidating } = useSWR('/api', fetcher)
console.log(data, error, isLoading, isValidating)
return null
}
在最糟的情況下(第一次請求失敗,然後重試成功),您會看到 4 行記錄
// console.log(data, error, isLoading, isValidating)
undefined undefined true true // => start fetching
undefined Error false false // => end fetching, got an error
undefined Error true true // => start retrying
Data undefined false false // => end retrying, get the data
狀態變更是有意義的。但也表示我們的元件**渲染了 4 次**。
如果我們變更我們的元件,使其只使用 data
function App () {
const { data } = useSWR('/api', fetcher)
console.log(data)
return null
}
奇蹟發生了 — 現在只有 **2 次重新渲染**了
// console.log(data)
undefined // => hydration / initial render
Data // => end retrying, get the data
內部發生了完全相同的過程,第一次請求出現錯誤,然後我們從重試中取得資料。然而,**SWR 只更新元件使用的狀態**,現在只有 data
。
如果您不總是使用所有這 3 個狀態,您就已經從這項功能中受益。在 Vercel (在新分頁開啟),這項最佳化可減少約 60% 的重新渲染。
Tree Shaking
SWR 套件是 可 tree-shake (在新分頁開啟) 的,而且沒有副作用。這表示如果您只匯入核心 useSWR
API,則像 useSWRInfinite
這種未使用的 API 將不會被綁定到您的應用程式中。