---
# System prepended metadata

title: DataTable with SWR
tags: [web dev]

---

---
title: DataTable with SWR
tags: web dev
---

## 主角

- [SWR](https://swr.vercel.app/)
- [React Data Table Component](https://github.com/jbetancur/react-data-table-component)


## 範例與程式碼

https://codesandbox.io/s/datatable-with-swr-8606c
   
   
## 說明

這個 demo 展示了在換頁、換每頁顯示列數、排序時會觸發 SWR 去 fetch 資料。

「建立時間」跟「留言數」兩個欄可以排序，可以試試看。

![](https://i.imgur.com/txWkT0i.png)

useSWR 的第一個參數 `key`，會是第二個參數 `fetcher` 的參數，它可以單純是個 url，或也可以丟物件或陣列再由 fetcher 處理。
它叫做 `key` 顧名思義它會在 `key` 變更的時候去 trigger useSWR 做 fetch 的動作，另外 SWR 也會**依靠這個 key 來 cache 資料**，利用 JS 的 Map（以下稱做 `cache` ）。

舉例來說，把某欄排序過後再排序回來，會發現一樣的資料他**可能**不會 re-fetch，就是因為 `key` 相同所以返回 `cache[key]` 的資料。

為什麼說「可能」呢？因為 re-fetch 與否是有規則的。
> SWR 全名是 stale-while-revalidate，細節請參考 [Cache Control](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Headers/Cache-Control)。

在資料還是 fresh（小於 max-age）時會直接使用 `cache[key]` 的資料，在資料是 stale（介於 max-age 與 swr 之間）時會先 return `cache[key]` 然後背景去 re-fetch 新資料，也就是 revalidate，否則，資料就是完全過期 會直接捨棄舊資料並 re-fetch 新資料。

以下是 useSWR 一些進階的功能

- 這個 `cache` 是全域的，即使在不同的元件，只要 useSWR 的 `key` 相同，他們就會共用 `cache[key]`。
- 在離開當前 tab 又重新回來時，若超過個幾秒鐘，會在回來時自動 re-fetch。
- 同上，據說 focus event 也會觸發，但我沒有研究，請看官方文件說明。
- 可靈活運用，例如預先 fetch 下一頁的資料，[範例](https://swr.vercel.app/docs/pagination)

還有另一個 useSWRInfinite 的 API，日後有空會再研究，目前基礎的需求應該還不至於要把他們搬出來

我目前是認為 useSWR 讓我們寫 data fetch 更方便，用更精簡的程式碼，而且預設的快取夠用，能提升使用者瀏覽資料的體驗。
精簡化程式碼例如像是 isLoading, isError 就不用自己宣告 state 來控。
在範例中我也運用了 useMemo 來取代我們常用的 useEffect

至於其他的特色是否要用，我認為可以之後有需求時再看就好。
例如 polling 他也有方便的寫法，preload, prefetch 都有相關的文件可以參考。

題外話，我在 [next-realworld-example-app](https://github.com/reck1ess/next-realworld-example-app/blob/master/components/article/ArticlePreview.tsx) 中看到他們也使用 useSWR 來 fetch LocalStorage 的資料，蠻有趣的。

參考資料
- [Keeping things fresh with stale-while-revalidate](https://web.dev/stale-while-revalidate/)


## Data table

### 自定義 sort

[文件](https://github.com/jbetancur/react-data-table-component#sorting) 上寫得無敵清楚，主要是 `sortServer` 搭配 `onSort` 來自定義。

若只有使用 `onSort`，那 DataTable 預設的排序行為還是會發生，你會看到 UI 閃一下，因為他除了執行你的 `onSort` 也會**排序當前的資料**，所以若要關閉這個預設行為請參考 `sortServer`。

### 自定義 pagination / pagination component

[文件](https://github.com/jbetancur/react-data-table-component#pagination) 一樣超級清楚，同理可以使用 `paginationServer` 搭配 `onChangePage` 來自定義。

其他的內容我就不贅述了，官方也有提供 [Demo](https://jbetancur.github.io/react-data-table-component/?path=/story/pagination--custom-component-material-ui)。


大概是醬，內容有問題請告訴我！