--- 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)。 大概是醬,內容有問題請告訴我!