iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
自我挑戰組

SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭系列 第 10

[Day10] 可以 call 一次 API 就解決的事,你為什麼要 call 很多次呢?來用用 useSWR 吧!

  • 分享至 

  • xImage
  •  

本日正文

無論是用 fetch 還是 axios
只要你有發出請求,
就會真的去抓取一次資料再回傳給你。

這邊我先用昨天的 axios 範例,
埋一個 dataFetchTimes
在發 axios.get 請求之後 dataFetchTimes 就+1,
讓我們來看一下:
axios次數
可以看到因為我送了 7 次請求,
所以也真的去 call API 7 次,
可是發現這個資料的變動頻率並沒有這麼高,
是一天才會變動一次的資料,
這樣我一直去 call 是不是很沒效率呢?
尤其是資料量如果很大的時候,
對 API 或是前端都會增加 loading。
有沒有辦法可以把 call API 回傳的資料先暫存起來,
等到有變動再去 call 就好呢?

那今天要介紹的 useSWR 就可以做到這件事哦!
useSWR 是開發 Next.js 的公司 Vercel 所發展出來的 React Hooks,
SWR 是 stale-while-revalidate 的縮寫,
顧名思義,第一次抓取資料就是會先將資料存至 cache (stale),
直到下一次 fetch 資料(revalidate),才會再拿到最新的資料。

使用 useSWR 之前一樣要先安裝跟 import,
像這樣:
https://ithelp.ithome.com.tw/upload/images/20220911/20129873AdAqSsLcaY.png

那我們就先來試一下 useSWR 該怎麼使用:

import useSWR from 'swr';

... (略)

const fetcher = url => axios.get(url).then(res => res.data);
const { data, error } = useSWR(sourceUrl, fetcher);

useEffect(() => {
    if (!data) return;
    console.log(data);
    setdataResult(data.records.location);
    setDataFetchTimes(dataFetchTimes+1);
}, [data]);

useEffect(() => {
    if (!dataResult) return;
    console.log(dataResult);
    setDataSearchArea(dataResult.filter((d) => d.locationName === searchArea));
}, [dataResult]);

... (略)

執行的結果如下:

可以看到只有一開始 initial 會去抓一次資料,
後續就不會一直再去 fetch 了。

那麼再來解釋一下這兩行,

const fetcher = url => axios.get(url).then(res => res.data);
const { data, error } = useSWR(sourceUrl, fetcher);

首先先看一下第二行,
意思是你透過 useSWR 去 fetch 資料,
這個 request 會回傳兩個值:data (回傳的資料) error(若有錯誤的時候會回傳)

那麼你要如何 fetch 呢?
就會定義在 useSWR 的第二個參數 fetcher
於是我們可以再回過頭看第一行,
這個 fetcher 可以是任何非同步的 function,
像是 fetch, axios 都可以,
更多的 fetcher 設定方法可以參考官方說明文件:Data Fetching

不過如果只是這樣,
好像還是感受不到 useSWR 只抓一次資料的好處,
這邊改寫一下範例,
假設區域現在我們弄成三個:
臺北市、臺中市、臺南市
https://ithelp.ithome.com.tw/upload/images/20220911/20129873HZgZObapXW.png

然後根據我們點的區域就會顯示不同區域的資料,
改寫如下:

... (略)

useEffect(() => {
	if (!dataResult) return;
	setDataSearchArea(dataResult.filter((d) => d.locationName === searchArea));
}, [dataResult, searchArea]); // 這邊多加一個 searchArea,偵測 searchArea 就要執行

... (略)

<Flex justifyContent="center">
  <Button mx={2} onClick={() => setSearchArea('臺北市')}>臺北市</Button>
  <Button mx={2} onClick={() => setSearchArea('臺中市')}>臺中市</Button>
  <Button mx={2} onClick={() => setSearchArea('臺南市')}>臺南市</Button>
</Flex>

執行結果:

雖然是不同區域,
但其實資料來源都是來自同一份,
使用 useSWR
就不會隨著我們點了不同按鈕又再去抓取一次資料。

因此像是這種資料異動頻率不高加上資料量大的時候,
比起單純用 fetch, axios 去抓取資料,
會使用 useSWR 無論是對前端或是後端的 loading 會是更佳的選擇。

今天終於來到第10天,
第一階段關於 call API 拿資料也告一段落,
第二階段準備進入 call API 做資料的 insert, update, delete
那就明天再見啦~~~

參考文章

SWR - React Hooks for Data Fetching
React SWR | 取得遠端資料的殺手級函式庫
超香的react data fetching library - SWR,與嘗試解釋它背後的實作原理
#09 No-code 之旅 — 怎麼在 Client-side 抓取資料?SWR 簡介

後記

其實真的是因為參加鐵人賽,
才去把這些事情搞清楚,
不然之前的我只是懵懵懂懂跟著寫而已,
並不是真的知道為什麼要這樣寫。

本來參加鐵人賽有點焦慮,
就是覺得是不是自己一定要寫出很言之有物的內容呢?
但回到參加鐵人賽的初衷就是要讓(ㄅㄧ)自己去學習、複習這樣,

每天進步一點點,在終點遇見更好的自己。

這句話是我偶然看到某位大大的部落格寫到的,
也跟大家分享,希望鐵人賽的終點我也能有所成長進步:)

我還在學習的路上,
若我有缺漏、錯誤之處,也請不吝鞭策指教,感恩恩 m(_ _)m

https://ithelp.ithome.com.tw/upload/images/20220911/20129873keLMe6GvgG.png


上一篇
[Day9] 來認識 axios 吧!之「既生 fetch,何生 axios?」
下一篇
[Day11] 前端也可以自己開 API!讓你了解後端的好幫手~ JSON Server
系列文
SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言