useNotificationCenter
useNotificationCenter
is a headless hook to build your notification center on top of react-toastify. In short, every time you call toast
or any other variants like toast.update
, toast.promise
, toast.info
, etc, the notification will be added to the toast center.
It offers a lot of flexibility out of the box like sorting
, filtering
, etc...
Check the example below.
Another example using MUI.
Importβ
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
Initial parametersβ
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
interface Data {
exclude: boolean
}
function App(){
const { notifications } = useNotificationCenter<Data>({
data: [
{id: "anId", createdAt: Date.now(), data: { exclude: false }},
{id: "anotherId", createdAt: Date.now(), data: { exclude: true }}
],
sort: (l, r) => l.createdAt - r.createdAt,
filter: (item) => item.data.exclude === false
})
}
Parameter | Description |
---|---|
data?: NotificationCenterItem<Data>[] | Initial data to rehydrate the notification center. Useful if you want to persist the content of the notification center |
sort?: (l: NotificationCenterItem<Data>, r: NotificationCenterItem<Data>): number | By default, the notifications are sorted from the newest to the oldest using the createdAt field. Use this to provide your sort function |
filter?: (item: NotificationCenterItem<Data>): boolean | Keep the toast that meets the condition specified in the callback function. |
All parameters are optional
APIβ
The hook gives you access to several values and functions. Let's view them one by one.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
const {
notifications,
clear,
markAllAsRead,
markAsRead,
add,
update,
remove,
find,
sort,
unreadCount
} = useNotificationCenter()
notifications
β
Contains an array of NotificationItem
. The NotificationItem
has the following interface
interface NotificationCenter <Data = {}> {
id: Id
read: boolean;
createdAt: number;
data: Data;
content?: React.ReactNode
theme?: Theme
type?: TypeOptions;
isLoading?: boolean;
containerId?: Id;
icon?: React.ReactNode | false;
}
Most of the properties are populated when you display a notification on the screen using the toast
function. A typical usage would look like this.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications } = useNotificationCenter()
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>id: {notification.id}</span>
<span>createdAt: {notification.createdAt}</span>
<p>content: {notification.content}</p>
{/* you get the idea, you are free to use the properties the way that best suits your needs */}
</li>
))}
</ul>
)
}
The content
contains the value that is displayed when calling the toast function. Use data
if you want more control.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
interface Data {
title: string
text: string
}
// somewhere in your app
toast("Hello", {
data: {
title: "Hello",
text: "Lorem ipsum dolor..."
}
})
function App(){
const { notifications } = useNotificationCenter<Data>()
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>id: {notification.id}</span>
<span>createdAt: {notification.createdAt}</span>
<p>title: {notification.data.title}</p>
<p>text: {notification.data.text}</p>
</li>
))}
</ul>
)
}
clear
β
Remove all notifications from the notification center.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, clear } = useNotificationCenter()
return (
<div>
<button onClick={clear}>clear</button>
<div>{notifications.length}</div>
</div>
)
}
markAllAsRead
β
Mark all notifications as read.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, markAllAsRead } = useNotificationCenter()
return (
<div>
<button onClick={markAllAsRead}>Mark all as read</button>
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>read: {notification.read}</span>
</li>
))}
</ul>
</div>
)
}
markAllAsRead
accepts an optional boolean argument. It's only useful to mark all notifications as not read.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, markAllAsRead } = useNotificationCenter()
return (
<div>
<button onClick={() => markAllAsRead(false)}>Mark all as not read</button>
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>read: {notification.read}</span>
</li>
))}
</ul>
</div>
)
}
Calling markAllasRead()
is equivalent to markAllAsRead(true)
// function signature
markAllAsRead(read?: boolean): void
markAsRead
β
Mark one or more notifications as read.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, markAsRead } = useNotificationCenter()
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>read: {notification.read}</span>
<button onClick={() => markAsRead(notification.id)}>mark as read</button>
</li>
))}
</ul>
)
}
You can also provide an array of ids to mark multiple notifications as read.
markAsRead(["a","list", "of", "id"])
Similar to markAllAsRead
, this function accepts an optional boolean argument. It's only useful to mark the notifications as not read.
markAsRead(notification.id, false)
// works for an array of ids as well
markAsRead(["a","list", "of", "id"], false)
unreadCount
β
Contains the number of unread notifications.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { unreadCount } = useNotificationCenter()
return (
<div>{unreadCount}</div>
)
}
remove
β
Remove one or more notifications.
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, remove } = useNotificationCenter()
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<button onClick={() => remove(notification.id)}>remove</button>
</li>
))}
</ul>
)
}
To remove multiple notifications at once, you can pass an array of ids.
remove(["a","list", "of", "id"])
sort
β
By default, the notifications are sorted from the newest to the oldest using the createdAt
field. This can be changed anytime and you are free to use whatever field you want.
import { useNotificationCenter, NotificationCenterItem } from "react-toastify/addons/useNotificationCenter"
function App(){
const { notifications, sort } = useNotificationCenter()
const sortAsc = () => {
sort((l: NotificationCenterItem, r: NotificationCenterItem) => l.createdAt - r.createdAt)
}
return (
<div>
<button onClick={sortAsc}>Oldest to newest</button>
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>{notification.id}</span>
</li>
))}
</ul>
</div>
)
}
Another example, using a field different from createdAt
. We can imagine that the notification contains an order
field under data
.
// somewhere in your app
toast("hello", {
data: {
order: 1
}
})
import { useNotificationCenter, NotificationCenterItem } from "react-toastify/addons/useNotificationCenter"
interface Data {
order: number
}
function App(){
const { notifications, sort } = useNotificationCenter<Data>()
const sortAsc = () => {
sort((l: NotificationCenterItem, r: NotificationCenterItem) => l.data.order - r.data.order)
}
return (
<div>
<button onClick={sortAsc}>Oldest to newest</button>
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>{notification.id}</span>
</li>
))}
</ul>
</div>
)
}
add
β
Let you add a notification without calling toast
. This can be useful in many cases, job listener, global store, etc...
import { useEffect } from "react"
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
import { jobListener } from "my-job-listener"
function App(){
const { notifications, add } = useNotificationCenter()
useEffect(() => {
const unsub = jobListener.on("jobCreate",(job) => {
add({ id: job.id, content: job.notification.content })
})
// although the reference of `add` changes for every render
// you can safely omit it from the dependency array
}, [])
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>{notification.id}</span>
</li>
))}
</ul>
)
}
- If the id is already in use, the function will return
null
and nothing will happens.
add({ id: "an existing id" }) // return null
- If you omit the
id
, one is generated for you.
add({ content: "hello" }) // return generated id
- You can also override the default values for
createdAt
andread
add({
// same as default value π
createdAt: Date.now(),
read: true
})
update
β
Let you update a notification without calling toast.update
. This can be useful in many cases, job listener, global store, etc...
import { useEffect } from "react"
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
import { jobListener } from "my-job-listener"
function App(){
const { notifications, update } = useNotificationCenter()
useEffect(() => {
const unsub = jobListener.on("jobUpdate", (job) => {
update(job.id, { content: job.notification.content, data: { jobType: job.type } })
})
// although the reference of `update` changes for every render
// you can safely omit it from the dependency array
}, [])
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>{notification.id}</span>
</li>
))}
</ul>
)
}
- if the given id does not exist, null is returned
update("nonExistingId", {content: "hello"}) // return null
find
β
Let you retrieve one or more notifications. This can be useful in many cases, job listener, global store, etc...
import { useEffect } from "react"
import { useNotificationCenter } from "react-toastify/addons/useNotificationCenter"
import { jobListener } from "my-job-listener"
function App(){
const { notifications, find } = useNotificationCenter()
useEffect(() => {
const unsub = jobListener.onChange((job) => {
const notification = find(job.id);
if(notification) {
// do something if it already exist, for example update it
} else {
// do something if it does not exist, for example add it
}
})
// although the reference of `find` changes for every render
// you can safely omit it from the dependency array
}, [])
return (
<ul>
{notifications.map(notification => (
<li key={notification.id}>
<span>{notification.id}</span>
</li>
))}
</ul>
)
}