iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

React Hook 不求人,建立自己的 Hook Libary系列 第 20

[DAY 20] 自己的Hook自己做!useTabs 想開幾個頁籤都可以?! (下)

  • 分享至 

  • xImage
  •  

承上篇,核心的 Tabs 其實已經建立好了,當內容不能呈現出來就不算真正的完成!因此本篇來看看要如何顯示對應的資料。

開始!

簡短回顧一下我們的 state 長什麼樣子:

{
  currentTab: null,  //目前瀏覽Tab的id
  storedTabs: [...], //存放的Tab的id們
}

顯示詳細資料

通常 Tabs 元件會依照實際的項目數量搭配對應的 Panels,也就是說有幾個分頁,就會有幾組頁面要顯示:

上圖擷取 MUI 的範例,一個Tab對應一個Panel。

不過由於我們的Panel都是呈現訂單,既然如此只需要一個 Panel ,再把 id 傳入,讓 OrderPanel 可以透過 id 去打API抓取資料回來顯示:

<Tabs>
  {/* 忽略 */}
</Tabs>
<OrderPanel key={tabs.currentTab} orderId={tabs.currentTab} />

其中 Key 是比較關鍵的地方,實作細節不一,(可能)會遇到資料顯示不正確,這時候可以運用 Key 的機制來重新渲染整個元件。

依照情境,你也可以傳入整包訂單的資料。

實際上 <OrderPanel /> 裡面就單純只是資料的排版與顯示,很純!(就不範例了)

其實非常簡單,基本的功能這樣就完成了,簡單展示一次:

其他功能(全關、關閉其他分頁)

但這樣就完成好像太...水了!

常常瀏覽網站或是VSC要關閉時,會用到全部關閉或是關閉其他分頁的功能,

老闆:「這看起來很實用,不然就加一加吧!」

我: (內心: (/゚Д゚)/你以為想加就加)

接下來就是:

  • 右鍵點擊選單
  • 關閉全部
  • 關閉其他

右鍵點擊選單

可以使用 onContextMenu 搭配 Menu + PopOver 等方式製作,製作方式請容許先略過,簡單來說就是點右鍵開啟選單,留意的是這邊記得 event.preventDefault() 不然還是會看到原本的選單。

關閉事件

而只需要把對應的事件傳入即可:

  • 關閉
  • 關閉全部
  • 關閉其他
<OrderTab
  {...忽略其他}
  onClose={() => tabDispatch("REMOVE", tab.id)} //重複使用的關閉
  onCloseAll={() => tabDispatch("RESET")} //關閉全部
  onCloseOthers={() => tabDispatch("ONLY", tab.id)} //關閉其他
/>

在 useTabs 中的 reducer 新增兩種方式:

case "RESET": {
  return initValue
}
case "ONLY": {
  const only = state.storedTabs.find((tab) => tab.id === payload)

  return {
    currentTab: payload,
    storedTabs: only ? [only] : [],
  }
}
  • RESET 關閉全部,單純就是回歸到最初的狀態
  • ONLY 關閉其他,則是藉由傳入的id,找到後並保留下來

最後就是...完成啦!

結語

可以延伸功能,像是 drag and drop(拖曳) 來移動位置,或是實務上遇到複雜的內容,可以再搭配 Context Provider 把 useTabs 包裝進去傳遞給跨界 子民? 子元件來使用。

DEMO 最後奉上


上一篇
[DAY 19] 自己的Hook自己做!useTabs 想開幾個頁籤都可以?! (上)
下一篇
[DAY 21] 不要再掐指算時辰啦!與時間套件一起準備當時空旅人吧!
系列文
React Hook 不求人,建立自己的 Hook Libary30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言