New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

react-notification-core

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-notification-core

Core notification functionality for React applications

latest
Source
npmnpm
Version
1.0.5
Version published
Maintainers
1
Created
Source

React Notification Core

npm version Downloads TypeScript PRs Welcome

A lightweight, UI-agnostic notification management library for React applications with TypeScript support.

Table of Contents

✨ Features

  • 🔄 Complete State Management: Comprehensive notification state handling out of the box
  • 🎣 Flexible Hooks: Customizable hooks for notification functionality
  • ⏱️ Automatic Polling: Built-in polling system with configurable intervals
  • 💾 Persistence: Optional local/session storage integration
  • 🔍 Filtering & Grouping: Powerful utilities for organizing notifications
  • 📊 TypeScript Support: Full type definitions for improved developer experience
  • 🔄 Async Support: First-class async/await support with robust error handling
  • 🔁 Retry Mechanism: Configurable retry logic for failed API calls
  • 🎨 UI-Agnostic: Bring your own UI components

📦 Installation

# Using npm
npm install react-notification-core

# Using yarn
yarn add react-notification-core

# Using pnpm
pnpm add react-notification-core

🎮 Demo

See React Notification Core in action with our example implementations:

🚀 Quick Start

Here's a basic implementation to get you started:

import React from 'react'
import { NotificationProvider, useNotifications } from 'react-notification-core'

// API functions to fetch and manage notifications
const fetchNotifications = async () => {
  const response = await fetch('/api/notifications')
  return response.json()
}

const markAsRead = async (id) => {
  await fetch(`/api/notifications/${id}/read`, { method: 'PUT' })
}

const markAllAsRead = async () => {
  await fetch('/api/notifications/read-all', { method: 'PUT' })
}

const deleteNotification = async (id) => {
  await fetch(`/api/notifications/${id}`, { method: 'DELETE' })
}

// Your notification UI component
function NotificationList() {
  const {
    notifications,
    unreadCount,
    markAsRead,
    markAllAsRead,
    deleteNotification,
    refreshNotifications,
    isLoading,
    error,
  } = useNotifications()

  if (isLoading) return <div>Loading notifications...</div>
  if (error) return <div>Error: {error.message}</div>

  return (
    <div>
      <header>
        <h2>Notifications ({unreadCount} unread)</h2>
        <div>
          <button onClick={refreshNotifications}>Refresh</button>
          <button onClick={markAllAsRead}>Mark all as read</button>
        </div>
      </header>

      {notifications.length === 0 ? (
        <p>No notifications</p>
      ) : (
        <ul>
          {notifications.map((notification) => (
            <li key={notification.id} className={notification.read ? 'read' : 'unread'}>
              <h3>{notification.title}</h3>
              <p>{notification.message}</p>
              <div>
                {!notification.read && (
                  <button onClick={() => markAsRead(notification.id)}>Mark as read</button>
                )}
                <button onClick={() => deleteNotification(notification.id)}>Delete</button>
              </div>
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

// App setup with provider
function App() {
  return (
    <NotificationProvider
      fetchNotifications={fetchNotifications}
      onMarkAsRead={markAsRead}
      onMarkAllAsRead={markAllAsRead}
      onDeleteNotification={deleteNotification}
      fetchOptions={{
        retryCount: 3,
        retryDelay: 1000,
        timeout: 10000,
      }}
    >
      <NotificationList />
    </NotificationProvider>
  )
}

export default App

🧩 Core Concepts

NotificationProvider

The NotificationProvider is the central component that manages notification state and provides context to child components.

Props

PropTypeRequiredDescription
fetchNotifications() => Promise<Notification[]>YesFunction to fetch notifications from your API
onMarkAsRead(id: string) => Promise<void>NoFunction to mark a notification as read
onMarkAllAsRead() => Promise<void>NoFunction to mark all notifications as read
onDeleteNotification(id: string) => Promise<void>NoFunction to delete a notification
fetchOptionsFetchOptionsNoOptions for fetch behavior (retries, timeout)
initialStateNotificationStateNoInitial state for notifications
childrenReactNodeYesChild components

Example

<NotificationProvider
  fetchNotifications={fetchNotificationsFunction}
  onMarkAsRead={markAsReadFunction}
  onMarkAllAsRead={markAllAsReadFunction}
  onDeleteNotification={deleteNotificationFunction}
  fetchOptions={{
    retryCount: 3,
    retryDelay: 1000,
    timeout: 10000,
  }}
  initialState={{
    notifications: [], // Initial notifications
    unreadCount: 0,
  }}
>
  <YourApp />
</NotificationProvider>

useNotifications Hook

The primary hook to access and manage notifications from anywhere in your component tree.

Returns

PropertyTypeDescription
notificationsNotification[]Array of all notifications
unreadCountnumberCount of unread notifications
isLoadingbooleanLoading state
errorError | nullError state
lastUpdatedDate | nullTimestamp of last update
addNotification(notification: Notification) => voidFunction to add a new notification
markAsRead(id: string) => Promise<void>Function to mark a notification as read
markAllAsRead() => Promise<void>Function to mark all notifications as read
deleteNotification(id: string) => Promise<void>Function to delete a notification
clearAllNotifications() => voidFunction to clear all notifications
refreshNotifications() => Promise<void>Function to refresh notifications

Example

function NotificationBadge() {
  const { unreadCount } = useNotifications()

  return <div className="badge">{unreadCount > 0 && <span>{unreadCount}</span>}</div>
}

🔧 Advanced Hooks

useNotificationPolling

Set up automatic polling for new notifications.

Options

OptionTypeDefaultDescription
enabledbooleantrueWhether polling is enabled
intervalnumber60000Polling interval in ms
onError(error: Error) => void-Error handler
retryCountnumber3Number of retries on failure
retryDelaynumber1000Delay between retries in ms

Returns

PropertyTypeDescription
refresh() => Promise<void>Function to manually refresh
stopPolling() => voidFunction to stop polling
startPolling() => voidFunction to start polling
isPolling() => booleanFunction that returns current polling state

Example

function NotificationContainer() {
  const { notifications } = useNotifications()
  const { stopPolling, startPolling, isPolling } = useNotificationPolling({
    interval: 30000, // Check every 30 seconds
    onError: (err) => console.error('Polling error:', err),
  })

  return (
    <div>
      <button onClick={isPolling() ? stopPolling : startPolling}>
        {isPolling() ? 'Pause Updates' : 'Enable Updates'}
      </button>
      <NotificationList notifications={notifications} />
    </div>
  )
}

useNotificationStorage

Persist notifications to localStorage or sessionStorage.

Options

OptionTypeDefaultDescription
storageKeystring'notifications'Key to use in storage
useSessionStoragebooleanfalseWhether to use sessionStorage instead of localStorage

Returns

PropertyTypeDescription
clearStorage() => voidFunction to clear storage

Example

function NotificationSettings() {
  const { clearStorage } = useNotificationStorage({
    storageKey: 'user-notifications',
  })

  return (
    <div>
      <h3>Notification Settings</h3>
      <button onClick={clearStorage}>Clear Notification History</button>
    </div>
  )
}

useNotificationFilters

Filter notifications based on various criteria.

Returns

PropertyTypeDescription
filteredNotificationsNotification[]Array of filtered notifications
filterByReadStatus(read: boolean) => voidFunction to filter by read status
filterByType(type: string) => voidFunction to filter by type
filterBySearch(term: string) => voidFunction to filter by search term
filterByDateRange(start: Date, end: Date) => voidFunction to filter by date range
resetFilters() => voidFunction to reset all filters
countsByTypeRecord<string, number>Object with counts by notification type
totalCountnumberTotal count of notifications
filteredCountnumberCount of filtered notifications
unreadCountnumberCount of unread notifications

Example

function NotificationFilters() {
  const { filterByReadStatus, filterByType, resetFilters, countsByType } = useNotificationFilters()

  return (
    <div className="filters">
      <button onClick={() => filterByReadStatus(false)}>Show Unread Only</button>
      <button onClick={() => filterByReadStatus(true)}>Show Read Only</button>

      <div className="type-filters">
        {Object.entries(countsByType).map(([type, count]) => (
          <button key={type} onClick={() => filterByType(type)}>
            {type} ({count})
          </button>
        ))}
      </div>

      <button onClick={resetFilters}>Clear Filters</button>
    </div>
  )
}

useNotificationGroups

Group notifications by date or custom criteria.

Returns

PropertyTypeDescription
groupedNotificationsRecord<string, Notification[]>Object with grouped notifications
groupsstring[]Array of group keys
getNotificationsForGroup(group: string) => Notification[]Function to get notifications for a group
groupedByTypeRecord<string, Notification[]>Object with notifications grouped by type

Example

function GroupedNotifications() {
  const { groupedNotifications, groups } = useNotificationGroups()

  return (
    <div>
      {groups.map((group) => (
        <div key={group}>
          <h3>{group}</h3>
          <ul>
            {groupedNotifications[group].map((notification) => (
              <li key={notification.id}>{notification.title}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  )
}

🛠️ API Reference

Utility Functions

The library provides several utility functions for working with notifications:

fetchWithRetry

function fetchWithRetry<T>(
  fn: () => Promise<T>,
  options?: {
    retryCount?: number
    retryDelay?: number
    timeout?: number
  }
): Promise<T>

Executes an async function with retry capability on failure.

formatTimestamp

function formatTimestamp(timestamp: Date | string | number, format?: string): string

Formats a timestamp into a human-readable string.

groupNotificationsByDate

function groupNotificationsByDate(
  notifications: Notification[],
  options?: {
    format?: string
    groupingFn?: (date: Date) => string
  }
): Record<string, Notification[]>

Groups notifications by date with customizable formatting.

filterNotifications

function filterNotifications(
  notifications: Notification[],
  filters: {
    read?: boolean
    type?: string
    search?: string
    dateRange?: { start: Date; end: Date }
  }
): Notification[]

Filters notifications based on specified criteria.

📝 TypeScript Support

This library is built with TypeScript and provides full type definitions:

// Base notification type
interface Notification {
  id: string
  title: string
  message: string
  read: boolean
  timestamp: string | number | Date
  type?: string
  [key: string]: any // Additional custom properties
}

// Provider context type
interface NotificationContextType {
  state: NotificationState
  dispatch: React.Dispatch<NotificationAction>
  api: {
    fetchNotifications: () => Promise<Notification[]>
    markAsRead?: (id: string) => Promise<void>
    markAllAsRead?: () => Promise<void>
    deleteNotification?: (id: string) => Promise<void>
  }
  fetchOptions: FetchOptions
}

// Notification state
interface NotificationState {
  notifications: Notification[]
  unreadCount: number
  isLoading: boolean
  error: Error | null
  lastUpdated: Date | null
}

// Fetch options for API calls
interface FetchOptions {
  retryCount?: number
  retryDelay?: number
  timeout?: number
}

// Polling hook options
interface UseNotificationPollingOptions {
  enabled?: boolean
  interval?: number
  onError?: (error: Error) => void
  retryCount?: number
  retryDelay?: number
}

Custom Type Extensions

You can extend the base Notification interface for custom notification types:

import { Notification } from 'react-notification-core'

// Extend with your custom properties
interface TaskNotification extends Notification {
  priority: 'low' | 'medium' | 'high'
  dueDate: string
  assignedTo: string
  project: string
}

⚠️ Error Handling

The library includes built-in error handling with retry capability:

// Example with custom error handling
function NotificationsErrorHandler() {
  const { error, isLoading, refreshNotifications } = useNotifications()

  useEffect(() => {
    if (error) {
      // Show toast notification
      toast.error(`Failed to load notifications: ${error.message}`)
    }
  }, [error])

  if (isLoading) return <LoadingSpinner />

  if (error) {
    return (
      <div className="error-container">
        <p>Could not load notifications</p>
        <button onClick={() => refreshNotifications()}>Try Again</button>
      </div>
    )
  }

  return <NotificationList />
}

🔍 Advanced Usage Examples

Custom Notification Types

import { NotificationProvider, useNotifications } from 'react-notification-core'
import type { Notification } from 'react-notification-core'

// Extend the base Notification type
interface CustomNotification extends Notification {
  priority: 'low' | 'medium' | 'high'
  category: string
  actions?: Array<{
    label: string
    action: string
  }>
}

// Use the custom type in your components
function NotificationList() {
  const { notifications } = useNotifications()
  const handleAction = (action: string, id: string) => {
    // Handle different action types
    switch (action) {
      case 'approve':
        approveRequest(id)
        break
      case 'reject':
        rejectRequest(id)
        break
      default:
        console.log(`Action ${action} for notification ${id}`)
    }
  }

  return (
    <ul className="notification-list">
      {notifications.map((notification) => {
        // Cast to custom type
        const customNotification = notification as CustomNotification

        return (
          <li
            key={notification.id}
            className={`
              notification-item 
              priority-${customNotification.priority}
              category-${customNotification.category.toLowerCase()}
              ${notification.read ? 'read' : 'unread'}
            `}
          >
            <h3>{customNotification.title}</h3>
            <p>{customNotification.message}</p>
            <span className="category">{customNotification.category}</span>

            <div className="actions">
              {customNotification.actions?.map((action) => (
                <button
                  key={action.action}
                  onClick={() => handleAction(action.action, notification.id)}
                  className={`action-btn ${action.action}`}
                >
                  {action.label}
                </button>
              ))}
            </div>
          </li>
        )
      })}
    </ul>
  )
}

Integration with External Notification Services

import { NotificationProvider } from 'react-notification-core'
import { initializeFirebase, getFirebaseMessaging } from './firebaseConfig'

function App() {
  // Initialize Firebase for push notifications
  useEffect(() => {
    initializeFirebase()

    // Request permission and get token
    const messaging = getFirebaseMessaging()
    messaging
      .requestPermission()
      .then(() => {
        return messaging.getToken()
      })
      .then((token) => {
        // Send token to your server
        registerDeviceToken(token)
      })

    // Handle incoming notifications
    messaging.onMessage((payload) => {
      // You can add the notification to your local state
      addNotification({
        id: payload.messageId,
        title: payload.notification.title,
        message: payload.notification.body,
        read: false,
        timestamp: new Date(),
        type: payload.data?.type || 'default',
        // Add any custom data from payload.data
        ...payload.data,
      })
    })
  }, [])

  // API handlers
  const fetchNotifications = async () => {
    const response = await fetch('/api/notifications')
    return response.json()
  }

  // Other handlers...

  return (
    <NotificationProvider
      fetchNotifications={fetchNotifications}
      // Other props...
    >
      <YourApp />
    </NotificationProvider>
  )
}

Real-time Notifications with WebSockets

import { useEffect } from 'react'
import { NotificationProvider, useNotifications } from 'react-notification-core'

function WebSocketNotificationHandler() {
  const { addNotification } = useNotifications()

  useEffect(() => {
    // Create WebSocket connection
    const socket = new WebSocket('wss://your-api.com/notifications')

    // Connection opened
    socket.addEventListener('open', (event) => {
      console.log('Connected to notification server')
    })

    // Listen for messages
    socket.addEventListener('message', (event) => {
      const notification = JSON.parse(event.data)
      addNotification({
        ...notification,
        read: false,
        timestamp: notification.timestamp || new Date(),
      })
    })

    // Handle errors
    socket.addEventListener('error', (event) => {
      console.error('WebSocket error:', event)
    })

    // Clean up on unmount
    return () => {
      socket.close()
    }
  }, [addNotification])

  return null // This component doesn't render anything
}

function App() {
  // API functions
  const fetchNotifications = async () => {
    // Your implementation
  }

  return (
    <NotificationProvider fetchNotifications={fetchNotifications}>
      <WebSocketNotificationHandler />
      <YourApp />
    </NotificationProvider>
  )
}

🤝 Contributing

Contributions are welcome! Please see our contributing guidelines for more details.

  • Fork the repository
  • Create your feature branch: git checkout -b feature/amazing-feature
  • Commit your changes: git commit -m 'Add some amazing feature'
  • Push to the branch: git push origin feature/amazing-feature
  • Open a Pull Request

📄 License

MIT

Community

Telegram

Built with ❤️ by Benjtalkshow

Keywords

react

FAQs

Package last updated on 21 May 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts