use-toast.tsx
Overview
use-toast.tsx provides a lightweight, React-based toast notification system inspired by the react-hot-toast library. It enables applications to display transient toast messages with optional actions, descriptions, and titles. The toasts are managed globally through a reducer pattern, supporting adding, updating, dismissing, and removing toast notifications.
This file exports two primary interfaces:
toast— a function to programmatically create and manage individual toast notifications.useToast— a React hook that provides reactive toast state and control methods to components.
Detailed Explanation
Types and Constants
TOAST_LIMIT
Maximum number of active toasts allowed concurrently (set to 1).TOAST_REMOVE_DELAY
Delay (in milliseconds) before a dismissed toast is fully removed from state (set to 1,000,000 ms ≈ ~16.7 minutes).ToasterToast
ExtendsToastPropswith additional properties:id: string— Unique identifier for the toast.title?: React.ReactNode — Optional title node.
description?: React.ReactNode — Optional description node.
action?: ToastActionElement — Optional action element.
actionTypes
Enum-like object defining action type strings for reducer actions:'REMOVE_TOAST'
Action
Union type representing possible reducer actions, each containing a specific payload relevant to the action type.State
Interface defining the toast state shape:toasts: ToasterToast[]— Array of active toast objects.
Internal Variables
count— Internal counter for generating unique toast IDs.toastTimeouts— A Map<string, ReturnType> used to track scheduled removal timeouts for toasts.listeners— Array of state update callbacks registered by components usinguseToast.memoryState— In-memory representation of the current toast state, used for synchronization.
Functions and Methods
genId(): string
Generates a unique string ID for each toast by incrementing an internal counter and wrapping around at Number.MAX_SAFE_INTEGER.
Usage example:
const id = genId(); // "1", "2", "3", ...
addToRemoveQueue(toastId: string): void
Schedules a toast for removal after TOAST_REMOVE_DELAY. If a removal timeout already exists for this toast, it does nothing.
Sets a
setTimeoutthat dispatches aREMOVE_TOASTaction after the delay.Stores the timeout handle in
toastTimeouts.
Implementation detail: This delayed removal mechanism allows toasts to have a "dismissed" state before being completely removed, enabling animations or other UI effects.
reducer(state: State, action: Action): State
Reducer function managing the toast state based on dispatched actions:
ADD_TOAST
Adds a new toast to the front of the toast array while respectingTOAST_LIMIT.UPDATE_TOAST
Updates an existing toast by merging provided partial props, identified byid.DISMISS_TOAST
Marks a toast (or all toasts if no ID is provided) as dismissed (open: false).
Also schedules removal viaaddToRemoveQueue.REMOVE_TOAST
Removes a toast by ID, or clears all toasts if no ID provided.
Important:
The reducer contains side effects (addToRemoveQueue) within the DISMISS_TOAST case. This is noted as a deliberate simplification.
dispatch(action: Action): void
Updates memoryState by applying the reducer, then notifies all registered listeners with the new state.
toast(props: Omit<ToasterToast, 'id'>): { id: string; dismiss: () => void; update: (props: ToasterToast) => void }
Primary API to create a toast:
Generates a unique ID.
Dispatches an
ADD_TOASTaction with the toast props, settingopen: trueand attaching anonOpenChangecallback that dismisses the toast when closed.Returns an object with:
id— the toast's unique identifier.dismiss()— function to dismiss the toast.update(props)— function to update the toast's properties.
Usage example:
const myToast = toast({
title: "Success",
description: "Your action was successful!",
action: <button onClick={() => alert('Clicked!')}>Undo</button>,
});
// Later update the toast
myToast.update({ description: "Updated description" });
// Dismiss the toast
myToast.dismiss();
useToast(): { toasts: ToasterToast[]; toast: typeof toast; dismiss: (toastId?: string) => void }
React hook exposing toast state and control methods:
Keeps local React state synchronized with the internal
memoryStatevia a subscription tolisteners.Returns:
toasts— current array of active toasts.toast— the toast creation function.dismiss(toastId?)— function to dismiss a specific toast or all toasts if no ID is provided.
Usage example:
function MyComponent() {
const { toasts, toast, dismiss } = useToast();
React.useEffect(() => {
const t = toast({ title: "Hello", description: "This is a toast" });
// Auto-dismiss after 5 seconds
setTimeout(() => t.dismiss(), 5000);
}, [toast]);
return (
<div>
{toasts.map(t => (
<ToastComponent key={t.id} {...t} />
))}
</div>
);
}
Implementation Details and Algorithms
Global State with Reducer: The toast system uses a reducer and a global in-memory state (
memoryState) to manage toasts, enabling centralized control.Listeners for React Sync: Components subscribe via the
listenersarray to be notified of state changes, ensuring React components stay in sync with the toast state.ID Generation: A simple incrementing counter with wrap-around guarantees unique toast IDs.
Toast Removal Workflow: When a toast is dismissed (
open: false), it is scheduled for removal after a long delay (TOAST_REMOVE_DELAY). This allows for UI exit animations or user interactions before the toast is permanently removed from state.Single Toast Limit: By default, only one toast can be active at a time, enforced by limiting the
toastsarray length in the reducer.Side Effects in Reducer: The
DISMISS_TOASTaction triggers side effects (scheduling removal timeouts), which is unusual for reducers but done here for simplicity.
Interaction with Other System Parts
Relies on
ToastPropsandToastActionElementtypes from@/registry/default/ui/toast, which presumably define the UI and behavior of individual toast components.The exported
toastfunction anduseToasthook are intended to be used by UI components and business logic layers to trigger and manage toast notifications.UI components consuming this module will render the toasts based on the
toastsstate provided byuseToast.
Visual Diagram
componentDiagram
direction TB
component "useToast Hook" as UseToast
component "toast() Function" as ToastFn
component "Reducer" as Reducer
component "Global State\n(memoryState)" as State
component "Listeners[]" as Listeners
component "Toast UI\nComponents" as UIComponents
UseToast --> State : subscribes to
UseToast --> Listeners : registers setState
UseToast --> Reducer : via dispatch()
ToastFn --> Reducer : dispatch actions (ADD/UPDATE/DISMISS)
Reducer --> State : updates
Reducer --> Listeners : notifies on state changes
Listeners --> UseToast : triggers setState
UseToast --> UIComponents : provides toasts & control
Summary
use-toast.tsx is a minimal, centralized toast notification manager for React applications that:
Manages toast lifecycle with add, update, dismiss, and remove operations.
Supports only one active toast at a time by default.
Provides a hook (
useToast) for React components to reactively consume toast state.Allows programmatic toast creation and updates via the
toastfunction.Uses a reducer pattern combined with global in-memory state and listener subscriptions to synchronize state with UI components.
This file is a core utility for handling toast notifications consistently across the application UI.