react-hot-toast
是一個專為 React 設計的輕量級通知提示(toast)套件。預設有成功、失敗、loading(Promise) 三種類型的提示功能,當然也可以透過屬性簡單的自訂義提示樣式、情境及通知訊息文字。同時,開發者也是目前 Vercel Analytics 的開發作者群之一,本身除了開發套件也是 UI 設計師,在套件官網和 toast 元件設計上都有很好的視覺體驗!
簡單 API 設計:其 API 設計得非常直觀,只需要在應用程式中設置 Toast 元件,再於需使用時調用 toast()
即可。
可客製化姓:雖然預設樣式已經很美了,但 react-hot-toast
依舊提供自訂義方法,可以修改 toast 的外觀和功能。
不僅僅是文字:除了顯示純文字的 toast,也可以是有 icon 的 toast 甚至是自定義的 React 組件。
支援 Promise 通知:可以顯示 loading 到成功或失敗的狀態。
無障礙性:react-hot-toast
考慮到了無障礙性,確保所有使用者都能獲得良好的體驗。
內建排隊系統:當多個 toast 通知同時觸發時,它們會自動排隊,而不是同時顯示,這可以避免用戶界面上的混亂。
輕量型套件:在 minified 和 gzipped 後的大小只有 4.8kb。
一進入官網有快速建置三步驟:安裝 → 設置 Toaster → 調用 toast()
,所以接下來就先依照這個步驟建置一個基本的 toast 吧!
npm i react-hot-toast
整個應用程式只需要設置一個 Toaster,在需要時以 toast()
調用,所以這個 Toaster 就必須設置在比較高的層級。在 Next.js 專案中,會設置在 root layout 中,這邊要注意的是,Toaster 是一個 Client Component 的 Provider 類型套件,所以會先將這個套件封裝為 ToastProvider ,再放置於 root layout。
// ToasterProvider.tsx
'use client'
import { Toaster } from 'react-hot-toast'
const ToasterProvider = () => {
return <Toaster />
}
export default ToasterProvider
接下來匯集到 Providers 中,再將 Providers 設於 root layout
// providers/Providers.tsx
'use client'
import React, { FC } from 'react'
import { ThemeProvider } from 'next-themes'
import { type ThemeProviderProps } from 'next-themes/dist/types'
import ToasterProvider from './ToastProvider'
const Providers: FC<ThemeProviderProps> = ({ children, ...props }) => {
return (
<ThemeProvider {...props}>
<ToasterProvider />
{children}
</ThemeProvider>
)
}
export default Providers
在需要的地方調用,例如 API 回傳成功後調用 toast()
import { toast } from 'react-hot-toast'
const onSubmit = async (values: FormValues) => {
try {
const { data: res } = await axios.put(`/api/user/${user?.id}`, values)
update({ admin: res.data })
toast.success('更新成功')
} catch (error) {
toast.error('更新失敗')
console.log(error)
}
}
react-hot-toast 的建置非常簡單,當然也可以依據不同的場景進行客製化設定或其他操作,其中預設就有不同狀態的顯示功能。
調用 toast() 可以設置最基本,無 icon 單純文字的樣式
使用 success 選項,會預設綠色勾勾 icon
toast.success('更新成功')
使用 error 選項,會預設紅色叉叉 icon
toast.error('更新失敗')
使用 loading 選項,會預設轉圈動畫,沒有時間長度設定。
toast.loading('更新中...')
使用 promise 選項,調用時需傳入兩個參數,第一個參數是 promise 的 function,第二個則是可以設定 loading、success、error 三個狀態時需要呈現的內容
toast.promise(
axios.put(`/api/user/${user?.id}`, values).then(({ data: res }) => {
update({ admin: res.data })
}),
{
loading: '更新中...',
success: '更新成功',
error: '更新失敗'
}
)
Toast 有提供樣式、位置、 toast 間間隔等,而各種狀態 toast 也可以設定其樣式、顯示時間長度、id、icon、className、style 等等。
const ToasterProvider = () => {
return (
<Toaster
position="top-right"
gutter={20}
reverseOrder={false}
containerStyle={{
position: 'relative',
top: '5rem',
marginRight: '1.5rem'
}}
toastOptions={{
loading: {
icon: '👏',
style: {
background: '#CEE0FD',
fontWeight: 'bold'
}
}
}}
/>
)
}
除了上面預設的各種狀態 toast,react-hot-toast
也提供客製化整個 toast 的屬性,可以使用 custom 屬性,在參數中可回傳一個 React Element 並且接收一個 toast props 可以調用 toast 功能,另外也支援 Tailwind CSS 的樣式設定。
toast.custom((t) => (
<div
className={`${
t.visible ? 'animate-enter' : 'animate-leave'
} max-w-md w-full bg-white shadow-lg rounded-lg pointer-events-auto flex ring-1 ring-black ring-opacity-5`}
>
<div className="flex-1 w-0 p-4">
<div className="flex items-start">
<div className="flex-shrink-0 pt-0.5">
<Image
className="h-10 w-10 rounded-full"
src={placeholder}
alt=""
/>
</div>
<div className="ml-3 flex-1">
<p className="text-sm font-medium text-gray-900">Renee Lan</p>
<p className="mt-1 text-sm text-gray-500">
要遲到了,太陽都要曬屁股了!
</p>
</div>
</div>
</div>
</div>
))
react-hot-toast
提供一個屬性可以調用後關閉通知 - toast.dismiss()
如果是 custom 的 callback 中調用,可以傳遞 toast id 指定該 toast 關閉,也可以單純調用 toast.dismiss()
,但有多個時就會關閉所有通知
<div className="flex border-l border-gray-200">
<button
onClick={() => toast.dismiss()}
className="w-full border border-transparent rounded-none rounded-r-lg p-4 flex items-center justify-center text-2xl font-medium text-primary-600 hover:text-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500"
>
<AiOutlineCloseCircle />
</button>
</div>
上述的功能其實已經可以滿足大部分需求,但 react-hot-toast
還提供了一個可以控制更細部功能的 hook - useToaster
:包含 toasts
、handlers
等回傳值。
toasts
- 為當前所有活躍中 toast 的陣列handlers
- 包含了 startPause
, endPause
, calculateOffset
, 和 updateHeight
等方法的物件
startPause
:暫停任何新的 toast 顯示。如果有排隊的 toast,它們將不會顯示,直到 endPause
被調用endPause
:結束暫停,允許 toast 再次顯示calculateOffset
:計算特定 toast 的偏移量updateHeight
:更新特定 toast 的高度一個小小的通知功能也是有很大的學問,個人最喜歡的是 Promise 功能,可以自動幫你捕捉 loading 到最後結果的狀態,也不需要太冗長的設定,是個非常實用的功能。另外 Issue 中有看到其他使用者希望可以像其他套件一樣加上進度條功能,關於這點作者表示進度條在這個通知功能上不是非常必要,但依舊可以使用客製化的方法自己加上!