javascript 48 lines · 7 steps

Building a toast notification system in React

A Context provider manages a list of transient toasts and exposes notify and dismiss to any component in the tree.

Explained by highlit
1import { createContext, useContext, useState, useCallback, useRef } from "react";
2 
3const ToastContext = createContext(null);
4 
5export function ToastProvider({ children, defaultDuration = 4000 }) {
6 const [toasts, setToasts] = useState([]);
7 const idRef = useRef(0);
8 
9 const dismiss = useCallback((id) => {
10 setToasts((prev) => prev.filter((t) => t.id !== id));
11 }, []);
12 
13 const notify = useCallback(
14 ({ message, variant = "info", duration = defaultDuration }) => {
15 const id = ++idRef.current;
16 setToasts((prev) => [...prev, { id, message, variant }]);
17 if (duration > 0) {
18 setTimeout(() => dismiss(id), duration);
19 }
20 return id;
21 },
22 [defaultDuration, dismiss]
23 );
24 
25 return (
26 <ToastContext.Provider value={{ notify, dismiss }}>
27 {children}
28 <div className="toast-viewport" role="region" aria-live="polite">
29 {toasts.map((toast) => (
30 <div key={toast.id} className={`toast toast--${toast.variant}`}>
31 <span>{toast.message}</span>
32 <button onClick={() => dismiss(toast.id)} aria-label="Dismiss">
33 ×
34 </button>
35 </div>
36 ))}
37 </div>
38 </ToastContext.Provider>
39 );
40}
41 
42export function useToast() {
43 const ctx = useContext(ToastContext);
44 if (!ctx) {
45 throw new Error("useToast must be used within a ToastProvider");
46 }
47 return ctx;
48}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Context lets you expose imperative actions like notify and dismiss to the whole tree without prop drilling.
  2. 2A ref-backed counter generates stable unique ids that survive re-renders without triggering them.
  3. 3Wrapping the context in a custom hook lets you enforce correct usage with a clear error.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a toast notification system in React — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code