使用 BlueprintJS + React Hook API + Typescript 打造後台系統高效能 Table元件
前言
想要使用 React 打造後台系統時,可能會選擇使用以下幾種框架來加快開發速度,
而由於有著大量複雜資料的需求,在這裡選擇使用 BlueprintJS 來作為後台系統的 UI 框架。
BlueprintJS 是由一家位於美國加州的大數據公司 Palantir 為大數據所打造的一套 UI 框架,打著用大數據預測未來的公司,而 Palantir 的意思是《魔戒》中能看到未來的水晶球。
你可能沒有聽過 BlueprintJS 但總該聽過 Typescript ,而 TSLint 這個 Typescript 的 Type 檢測工具正是 Palantir 這家公司團隊所開發的。TSLint in 2019。因此 BlueprintJS 是個有著為大數據打造及對 Typescript 的 lint rule 有深厚基礎的老爸所誕生的兒子。
正題
資料瀏覽性質高的後台系統最主要的資料瀏覽元件就是 Table ,因此我們就以 BlueprintJS 所設計的 Table 與 React Hook API 來包裝成我們所需要的 React Function Component.
Table 主要顯示的資料不外乎就是 Rows 與 Columns ,而 BlueprintJS 的 Table 設計與其他框架的 Table 的設計概念不太一樣,資料不是以 Row 的角度來做渲染,而是以 Column 與 Cell 的角度,藉由多個客製化的 Renderer 來優化整體的渲染效果,讓 Table 每一個 Cell 做到最小化的渲染。
這樣說可能有點抽象,一般來說,我們要顯示 Rows 的資料可能會把整個 Rows 的資料丟到 Table 元件裡,然後利用迴圈把整個 Rows 資料渲染出來,而每當 Rows 資料有變更時,整個迴圈再重跑一次再做渲染,因此當 Rows 的資料超過上百筆或上千筆時,重新渲染的代價非常高。
從官方給的展示代碼來看
從中可以看出幾點
- 傳給 Table 的 props 並不需要 Rows 資料,只需告訴 Table 需要幾列資料
- 可以決定要顯示幾個 Column 資料
- CellRenderer 有兩個參數 rowIndex 與 columnIndex (文件中有說明),兩者搭配就可以取得要顯示 Cell 資料
這表示說 BlueprintJS 的 Table 元件內並不需要維護複雜的 Rows 資料,只要使用各種 Renderer 來告訴元件如何顯示資料就行了。
那麼就接著根據官方文件給的資訊,來打造一個簡單的 Table 元件。
上面的代碼中,我使用了三個 Renderer ,分別是 cellRenderer, headerNameRenderer, columnHeaderCellRenderer 每個各自負責要渲染的資料,與資料管理沒有任何關聯;使用 React.memo 將元件包裝以及對每個Cell 都給予一個 Key 來優化效能。
接著這邊使用 NextJS 建立一個簡單頁面及一些資料來顯示 Table 內容,然後使用一個按鈕來點擊,隨機更新 Rows 的資料,再使用 React devtool 來查看元件更新的狀況。
結論
當 Rows 的資料更新時,只有資料變更的 Cell 會被重新渲染,這確實達到了我們期望的結果,在大量的 Rows 資料變更時,可以最小量化畫面的更新,而不會整個 Table 的 Rows 與 Columns 都重新的渲染。
比較遺憾的是,Columns 的 Header 在 Cell 渲染時也會重新渲染,目前尚未從官方 Github 中找出相關的 Solution ,若您有相關的意見或建議,還懇請請提出指教。