開始使用
安裝
在您的 React 專案目錄中,執行以下指令
pnpm add swr
快速開始
對於具有 JSON 資料的正常 RESTful API,首先您需要建立一個 fetcher
函式,它只是原生 fetch
的包裝函式
const fetcher = (...args) => fetch(...args).then(res => res.json())
如果您想使用 GraphQL API 或像 Axios 這樣的函式庫,您可以建立自己的 fetcher 函式。請查看這裡以取得更多範例。
然後您可以匯入 useSWR
,並開始在任何函式元件中使用它
import useSWR from 'swr'
function Profile () {
const { data, error, isLoading } = useSWR('/api/user/123', fetcher)
if (error) return <div>failed to load</div>
if (isLoading) return <div>loading...</div>
// render data
return <div>hello {data.name}!</div>
}
通常,請求有 3 種可能的狀態:「載入中」、「準備就緒」或「錯誤」。您可以使用 data
、error
和 isLoading
的值來判斷請求的目前狀態,並傳回對應的 UI。
使其可重複使用
在建構 Web 應用程式時,您可能需要在 UI 的許多地方重複使用資料。在 SWR 之上建立可重複使用的資料 Hook 非常容易
function useUser (id) {
const { data, error, isLoading } = useSWR(`/api/user/${id}`, fetcher)
return {
user: data,
isLoading,
isError: error
}
}
並在您的元件中使用它
function Avatar ({ id }) {
const { user, isLoading, isError } = useUser(id)
if (isLoading) return <Spinner />
if (isError) return <Error />
return <img src={user.avatar} />
}
透過採用這種模式,您可以忘記以命令式方式獲取資料:啟動請求、更新載入狀態,並傳回最終結果。相反地,您的程式碼更具宣告性:您只需要指定元件使用哪些資料。
範例
在實際範例中,我們的網站會顯示一個導覽列和內容,兩者都取決於 user
傳統上,我們在頂層元件中使用 useEffect
獲取一次資料,並透過 props 將其傳遞給子元件(請注意,我們目前不處理錯誤狀態)
// page component
function Page () {
const [user, setUser] = useState(null)
// fetch data
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data))
}, [])
// global loading state
if (!user) return <Spinner/>
return <div>
<Navbar user={user} />
<Content user={user} />
</div>
}
// child components
function Navbar ({ user }) {
return <div>
...
<Avatar user={user} />
</div>
}
function Content ({ user }) {
return <h1>Welcome back, {user.name}</h1>
}
function Avatar ({ user }) {
return <img src={user.avatar} alt={user.name} />
}
通常,我們需要將所有資料獲取保留在頂層元件中,並將 props 新增至樹狀結構中的每個元件。如果我們向頁面新增更多資料相依性,程式碼將變得更難以維護。
雖然我們可以避免使用 Context(在新分頁中開啟) 來傳遞 props,但仍然存在動態內容問題:頁面內容內的元件可以是動態的,而且頂層元件可能不知道其子元件需要哪些資料。
SWR 完美地解決了這個問題。使用我們剛剛建立的 useUser
Hook,程式碼可以重構為
// page component
function Page () {
return <div>
<Navbar />
<Content />
</div>
}
// child components
function Navbar () {
return <div>
...
<Avatar />
</div>
}
function Content () {
const { user, isLoading } = useUser()
if (isLoading) return <Spinner />
return <h1>Welcome back, {user.name}</h1>
}
function Avatar () {
const { user, isLoading } = useUser()
if (isLoading) return <Spinner />
return <img src={user.avatar} alt={user.name} />
}
現在資料繫結至需要資料的元件,而且所有元件彼此獨立。所有父元件都不需要知道任何關於資料或傳遞資料的事情。它們只是呈現。程式碼現在變得更簡單且更容易維護。
最棒的是,只會向 API 發送 1 個請求,因為它們使用相同的 SWR 金鑰,而且請求會自動去重複、快取和共用。
此外,應用程式現在具有在使用者焦點或網路重新連線時重新獲取資料的能力!這表示,當使用者的筆記型電腦從睡眠中喚醒,或他們在瀏覽器索引標籤之間切換時,資料將會自動重新整理。