I created a React application using Vite and TypeScript.
Then, I created a src/context
folder, and inside it, I made a file called alertContext.tsx
to handle alerts and notifications using React’s Context API.first I created ToastContext next created ToastProvider then created hooks for example :
1. notificationContext.jsx
Purpose:
This file defines the Toast Context — a global place to manage all toast messages (alerts/notifications) in your app.
Why Created It:
To allow any component in the app to trigger a toast (success, error, info, etc.) — without repeating logic everywhere.
import { createContext, useContext, useState, useCallback } from 'react'; import { v4 as uuidv4 } from 'uuid';
Imports needed to create context and manage state.
uuidv4()
gives each toast a unique ID.
Functions Inside:
addToast(message, type, duration)
Adds a new toast with a message, type (
info
,success
, etc.), and how long it should stay (default 3 seconds).Automatically removes the toast after the duration.
removeToast(id)
Removes the toast with the given ID.
<ToastContext.Provider value={{ addToast }}> {children} <div className="toast-container"> {toasts.map((toast) => ( <div key={toast.id} className={`toast ${toast.type}`}> {toast.message} </div> ))} </div> </ToastContext.Provider>
Wraps your app with a provider that shares the
addToast()
function.Also renders a
<div>
at the top of the page where all active toasts are shown.Usage:
Any component inside the provider can now call
addToast()
to show a notification.
// ToastContext.js import { createContext, useContext, useState, useCallback } from 'react'; import { v4 as uuidv4 } from 'uuid'; const ToastContext = createContext(); export const ToastProvider = ({ children }) => { const [toasts, setToasts] = useState([]); const removeToast = useCallback((id) => { setToasts((toasts) => toasts.filter((toast) => toast.id !== id)); }, []); const addToast = useCallback((message, type = 'info', duration = 3000) => { const id = uuidv4(); setToasts((prevToasts) => [...prevToasts, { id, message, type }]); setTimeout(() => { removeToast(id); }, duration); }, [removeToast]); return ( <ToastContext.Provider value={{ addToast }}> {children} <div className="toast-container"> {toasts.map((toast) => ( <div key={toast.id} className={`toast ${toast.type}`}> {toast.message} </div> ))} </div> </ToastContext.Provider> ); }; export const useToast = () => useContext(ToastContext);import { StrictMode } from 'react'
2. main.tsx
Purpose:
This is the main entry point app.
<StrictMode> <ToastProvider> <App /> </ToastProvider> </StrictMode>
wrapped your entire app inside
<ToastProvider>
.This makes the toast system available globally to every component.
3.
App.tsx
Purpose:
Main component of your app. You are testing and triggering toast messages here.
const { addToast } = useToast();
using the
useToast()
hook from the context to get access to theaddToast()
function.
import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' import App from './App.tsx' import { ToastProvider } from "./context/notificationContext.jsx" createRoot(document.getElementById('root')!).render( <StrictMode> <ToastProvider> <App /> </ToastProvider> </StrictMode>, )
import { useState } from 'react' import './App.css' import { useToast } from "./context/notificationContext.jsx" import Home from './home.tsx' console.log("useToast", useToast) function App() { const [count, setCount] = useState(0) const { addToast, toasts } = useToast(); console.log("toasts", toasts); return ( <> <button onClick={() => addToast('This is an info toast')}>Show Info Toast</button> <button onClick={() => addToast('Success!', 'success')}>Show Success Toast</button> <button onClick={() => addToast('Something went wrong!', 'error')}>Show Error Toast</button> <Home /> </> ) } export default App