0
# Notification Center
1
2
The Notification Center addon provides persistent notification management through a React hook-based API. Unlike regular toasts that automatically disappear, the notification center maintains a persistent list of notifications that users can manage manually.
3
4
## Package Information
5
6
The notification center is distributed as a separate addon:
7
8
- **Import Path**: `react-toastify/addons/use-notification-center`
9
- **Dependencies**: Requires `react-toastify` as a peer dependency
10
11
## Core Imports
12
13
```typescript
14
import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';
15
```
16
17
## Capabilities
18
19
### useNotificationCenter Hook
20
21
Main hook for managing persistent notifications with full CRUD operations and state management.
22
23
```typescript { .api }
24
/**
25
* React hook for managing a persistent notification center
26
* @param params - Optional configuration parameters
27
* @returns Notification center API with methods and state
28
*/
29
function useNotificationCenter<T = {}>(
30
params?: UseNotificationCenterParams<T>
31
): UseNotificationCenter<T>;
32
33
interface UseNotificationCenterParams<T = {}> {
34
/** Initial notifications to populate the center (for rehydration) */
35
data?: NotificationCenterItem<T>[];
36
/** Filter function to determine which notifications to include */
37
filter?: FilterFn<T>;
38
/** Sort function to order notifications */
39
sort?: SortFn<T>;
40
}
41
42
type FilterFn<T = {}> = (item: NotificationCenterItem<T>) => boolean;
43
type SortFn<T = {}> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;
44
45
interface UseNotificationCenter<T = {}> {
46
/** Array of all notifications in the center */
47
notifications: NotificationCenterItem<T>[];
48
/** Remove all notifications from the center */
49
clear(): void;
50
/** Mark all notifications as read or unread */
51
markAllAsRead(read?: boolean): void;
52
/** Mark specific notifications as read or unread */
53
markAsRead(id: Id | Id[], read?: boolean): void;
54
/** Remove specific notifications from the center */
55
remove(id: Id | Id[]): void;
56
/** Add a new notification to the center */
57
add(item: NotificationCenterItem<T>): void;
58
/** Update an existing notification */
59
update(id: Id, item: Partial<NotificationCenterItem<T>>): void;
60
/** Find notification(s) by ID */
61
find(id: Id): NotificationCenterItem<T> | undefined;
62
/** Sort notifications using a custom comparator */
63
sort(compareFn: SortFn<T>): void;
64
/** Number of unread notifications */
65
unreadCount: number;
66
}
67
```
68
69
**Basic Usage:**
70
71
```typescript
72
import React from 'react';
73
import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';
74
75
function NotificationCenter() {
76
const {
77
notifications,
78
clear,
79
markAllAsRead,
80
markAsRead,
81
remove,
82
unreadCount
83
} = useNotificationCenter();
84
85
return (
86
<div className="notification-center">
87
<div className="header">
88
<h3>Notifications ({unreadCount} unread)</h3>
89
<button onClick={() => markAllAsRead()}>Mark All Read</button>
90
<button onClick={clear}>Clear All</button>
91
</div>
92
93
<div className="notifications">
94
{notifications.map(notification => (
95
<div
96
key={notification.id}
97
className={`notification ${notification.read ? 'read' : 'unread'}`}
98
>
99
<div className="content">{notification.content}</div>
100
<div className="actions">
101
<button onClick={() => markAsRead(notification.id)}>
102
{notification.read ? 'Mark Unread' : 'Mark Read'}
103
</button>
104
<button onClick={() => remove(notification.id)}>Remove</button>
105
</div>
106
</div>
107
))}
108
</div>
109
</div>
110
);
111
}
112
```
113
114
### Adding Notifications
115
116
Add notifications to the center programmatically or from toast events.
117
118
```typescript { .api }
119
/**
120
* Add a new notification to the center
121
* @param item - The notification item to add
122
*/
123
add(item: NotificationCenterItem<T>): void;
124
```
125
126
**Manual Addition:**
127
128
```typescript
129
function MyComponent() {
130
const { add } = useNotificationCenter();
131
132
const addNotification = () => {
133
add({
134
id: Date.now().toString(),
135
content: "New notification message",
136
theme: "light",
137
type: "info",
138
read: false,
139
createdAt: Date.now(),
140
data: { source: 'manual' }
141
});
142
};
143
144
return <button onClick={addNotification}>Add Notification</button>;
145
}
146
```
147
148
**From Toast Events:**
149
150
```typescript
151
import { toast } from 'react-toastify';
152
import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';
153
154
function MyComponent() {
155
const { add } = useNotificationCenter();
156
157
const showToastAndAddToCenter = () => {
158
const toastId = toast.success("Operation completed", {
159
onClose: () => {
160
// Add to notification center when toast closes
161
add({
162
id: toastId.toString(),
163
content: "Operation completed successfully",
164
type: "success",
165
read: false,
166
createdAt: Date.now()
167
});
168
}
169
});
170
};
171
172
return <button onClick={showToastAndAddToCenter}>Show Toast</button>;
173
}
174
```
175
176
### Managing Read State
177
178
Control the read/unread state of notifications individually or in bulk.
179
180
```typescript { .api }
181
/**
182
* Mark all notifications as read or unread
183
* @param read - True to mark as read, false for unread (default: true)
184
*/
185
markAllAsRead(read?: boolean): void;
186
187
/**
188
* Mark specific notifications as read or unread
189
* @param id - Single ID or array of IDs to mark
190
* @param read - True to mark as read, false for unread (default: true)
191
*/
192
markAsRead(id: Id | Id[], read?: boolean): void;
193
```
194
195
**Usage Examples:**
196
197
```typescript
198
const { markAllAsRead, markAsRead, notifications } = useNotificationCenter();
199
200
// Mark all as read
201
markAllAsRead();
202
203
// Mark all as unread
204
markAllAsRead(false);
205
206
// Mark specific notification as read
207
markAsRead('notification-1');
208
209
// Mark multiple notifications as read
210
markAsRead(['notification-1', 'notification-2']);
211
212
// Mark as unread
213
markAsRead('notification-1', false);
214
215
// Toggle read state
216
const toggleRead = (id: string) => {
217
const notification = notifications.find(n => n.id === id);
218
if (notification) {
219
markAsRead(id, !notification.read);
220
}
221
};
222
```
223
224
### Removing Notifications
225
226
Remove individual notifications or clear the entire center.
227
228
```typescript { .api }
229
/**
230
* Remove specific notifications from the center
231
* @param id - Single ID or array of IDs to remove
232
*/
233
remove(id: Id | Id[]): void;
234
235
/**
236
* Remove all notifications from the center
237
*/
238
clear(): void;
239
```
240
241
**Usage Examples:**
242
243
```typescript
244
const { remove, clear } = useNotificationCenter();
245
246
// Remove single notification
247
remove('notification-1');
248
249
// Remove multiple notifications
250
remove(['notification-1', 'notification-2']);
251
252
// Clear all notifications
253
clear();
254
255
// Remove all read notifications
256
const removeAllRead = () => {
257
const readIds = notifications
258
.filter(n => n.read)
259
.map(n => n.id);
260
remove(readIds);
261
};
262
```
263
264
### Updating Notifications
265
266
Modify existing notifications in the center.
267
268
```typescript { .api }
269
/**
270
* Update an existing notification
271
* @param id - The ID of the notification to update
272
* @param item - Partial notification item with fields to update
273
*/
274
update(id: Id, item: Partial<NotificationCenterItem<T>>): void;
275
```
276
277
**Usage Examples:**
278
279
```typescript
280
const { update } = useNotificationCenter();
281
282
// Update notification content
283
update('notification-1', {
284
content: "Updated message content",
285
read: true
286
});
287
288
// Update notification data
289
update('notification-1', {
290
data: { ...existingData, priority: 'high' }
291
});
292
293
// Update notification theme
294
update('notification-1', {
295
theme: 'dark',
296
type: 'warning'
297
});
298
```
299
300
### Finding and Sorting
301
302
Search for specific notifications and customize the display order.
303
304
```typescript { .api }
305
/**
306
* Find a notification by ID
307
* @param id - The ID to search for
308
* @returns The notification item or undefined if not found
309
*/
310
find(id: Id): NotificationCenterItem<T> | undefined;
311
312
/**
313
* Sort notifications using a custom comparator function
314
* @param compareFn - Function to determine sort order
315
*/
316
sort(compareFn: SortFn<T>): void;
317
318
type SortFn<T> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;
319
```
320
321
**Usage Examples:**
322
323
```typescript
324
const { find, sort, notifications } = useNotificationCenter();
325
326
// Find specific notification
327
const notification = find('notification-1');
328
if (notification) {
329
console.log('Found:', notification.content);
330
}
331
332
// Sort by creation time (newest first)
333
sort((a, b) => b.createdAt - a.createdAt);
334
335
// Sort by read status (unread first)
336
sort((a, b) => {
337
if (a.read === b.read) return 0;
338
return a.read ? 1 : -1;
339
});
340
341
// Sort by type priority
342
const typePriority = { error: 0, warning: 1, info: 2, success: 3 };
343
sort((a, b) => typePriority[a.type] - typePriority[b.type]);
344
```
345
346
### Configuration Options
347
348
Initialize the notification center with custom settings and data.
349
350
```typescript { .api }
351
interface UseNotificationCenterParams<T = {}> {
352
/** Initial notifications to populate the center */
353
data?: NotificationCenterItem<T>[];
354
/** Maximum number of notifications to keep (oldest removed first) */
355
limit?: number;
356
/** Filter function to determine which notifications to include */
357
filter?: FilterFn<T>;
358
/** Sort function to order notifications */
359
sort?: SortFn<T>;
360
}
361
362
type FilterFn<T> = (notification: NotificationCenterItem<T>) => boolean;
363
type SortFn<T> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;
364
```
365
366
**Configuration Examples:**
367
368
```typescript
369
// Initialize with data and limit
370
const { notifications } = useNotificationCenter({
371
data: [
372
{
373
id: '1',
374
content: 'Welcome notification',
375
type: 'info',
376
read: false,
377
createdAt: Date.now()
378
}
379
],
380
limit: 50,
381
filter: (notification) => !notification.read, // Only show unread
382
sort: (a, b) => b.createdAt - a.createdAt // Newest first
383
});
384
385
// Filter for important notifications only
386
const { notifications: importantNotifications } = useNotificationCenter({
387
filter: (notification) =>
388
notification.data?.priority === 'high' || notification.type === 'error'
389
});
390
```
391
392
### Integration with Toast Events
393
394
Automatically populate the notification center from toast lifecycle events.
395
396
```typescript
397
import { toast } from 'react-toastify';
398
import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';
399
400
function IntegratedNotifications() {
401
const { add, notifications } = useNotificationCenter();
402
403
// Subscribe to toast events
404
React.useEffect(() => {
405
const unsubscribe = toast.onChange((payload) => {
406
if (payload.status === 'added') {
407
// Add to notification center when toast appears
408
add({
409
id: payload.id.toString(),
410
content: payload.content,
411
type: payload.type || 'default',
412
theme: payload.theme || 'light',
413
read: false,
414
createdAt: Date.now(),
415
data: payload.data
416
});
417
}
418
});
419
420
return unsubscribe;
421
}, [add]);
422
423
const showToast = () => {
424
toast.success("This will appear in both toast and notification center");
425
};
426
427
return (
428
<div>
429
<button onClick={showToast}>Show Toast</button>
430
<div>Notification Center has {notifications.length} items</div>
431
</div>
432
);
433
}
434
```
435
436
## Notification Item Type
437
438
```typescript { .api }
439
interface NotificationCenterItem<T = {}> {
440
/** Unique identifier for the notification */
441
id: Id;
442
/** Content to display (string, React node, or render function) */
443
content: ToastContent<T>;
444
/** Timestamp when notification was created */
445
createdAt: number;
446
/** Whether the notification has been read */
447
read?: boolean;
448
/** Toast type for styling and icons */
449
type?: TypeOptions;
450
/** Theme for styling */
451
theme?: Theme;
452
/** Custom data associated with the notification */
453
data?: T;
454
/** Custom icon for the notification */
455
icon?: ToastIcon;
456
}
457
```
458
459
## Advanced Patterns
460
461
### Persistent Storage
462
463
Save notification center state to localStorage:
464
465
```typescript
466
function usePersistentNotificationCenter<T>() {
467
const STORAGE_KEY = 'notification-center';
468
469
// Load initial data from storage
470
const loadInitialData = (): NotificationCenterItem<T>[] => {
471
try {
472
const stored = localStorage.getItem(STORAGE_KEY);
473
return stored ? JSON.parse(stored) : [];
474
} catch {
475
return [];
476
}
477
};
478
479
const nc = useNotificationCenter<T>({
480
data: loadInitialData()
481
});
482
483
// Save to storage whenever notifications change
484
React.useEffect(() => {
485
localStorage.setItem(STORAGE_KEY, JSON.stringify(nc.notifications));
486
}, [nc.notifications]);
487
488
return nc;
489
}
490
```
491
492
### Notification Categories
493
494
Group notifications by category:
495
496
```typescript
497
interface CategorizedNotification {
498
category: 'system' | 'user' | 'marketing';
499
priority: 'low' | 'medium' | 'high';
500
}
501
502
function CategorizedNotificationCenter() {
503
const { notifications, add } = useNotificationCenter<CategorizedNotification>();
504
505
const notificationsByCategory = React.useMemo(() => {
506
return notifications.reduce((acc, notification) => {
507
const category = notification.data?.category || 'system';
508
if (!acc[category]) acc[category] = [];
509
acc[category].push(notification);
510
return acc;
511
}, {} as Record<string, NotificationCenterItem<CategorizedNotification>[]>);
512
}, [notifications]);
513
514
return (
515
<div>
516
{Object.entries(notificationsByCategory).map(([category, items]) => (
517
<div key={category}>
518
<h4>{category} ({items.length})</h4>
519
{items.map(item => (
520
<div key={item.id}>{item.content}</div>
521
))}
522
</div>
523
))}
524
</div>
525
);
526
}
527
```