Sonner for React: Toast Notifications, Hooks & Customization
Short description: Pragmatic guide to installing and using sonner for React toast notifications—hooks, promise toasts, customization, accessibility, and real-world patterns.
Introduction: Why sonner?
Notifications are a small surface with a big job: communicate transient state without interrupting flow. The sonner library focuses on lightweight, performant toast notifications for React apps. It gives you hooks, a compact API, and sensible defaults so you can ship useful alerts fast.
Compared to heavier notification suites, sonner aims to be minimal but extensible. That means you get a tiny runtime footprint and the ability to replace or style the toast UI without fighting a monolith. This approach helps keep bundle sizes down and UX consistent.
Throughout this article you'll see practical patterns—installation, hooks usage, promise-based toasts, and customization—so you can integrate sonner into typical React architectures (SPA, SSR-aware routes, or component libraries).
Installing and setting up sonner
Getting started is straightforward. Install via npm or yarn and mount the provider in your app root. The provider manages the toast stack and exposes the API via hooks or direct imports.
Example install commands (one-liners):
npm install sonner
# or
yarn add sonner
After installation, add the <Toaster /> in your top-level component (often App.jsx or _app.jsx for Next.js). This is the only required UI element for sonner to render notifications. Keep the provider high enough to cover screen regions where toasts may appear.
For a step-by-step sonner tutorial that includes advanced patterns and example code, see this walkthrough.
Core concepts and React toast hooks
Sonner exposes a tiny API surface: the Toaster UI component and a set of programmatic helpers/hooks to push toasts. You’ll typically use a hook (or direct function) to trigger toasts from anywhere in your component tree.
Common operations include showing success/error/info toasts, updating a toast by id, and dismissing toasts programmatically. The hooks are designed to be composable with state and effects, so they fit naturally in React components and async flows.
Here's a compact example using a hook to fire a toast from a form submit handler:
import { toast } from 'sonner'
function onSave() {
// optimistic UI + toast
toast.success('Saved')
}
Because sonner is hook-friendly, you can build scaffolding around it: central notification services, reusable toast builders, or context-based wrappers that standardize messages and actions.
Promise toasts: handling async flows
One of sonner's most useful patterns is promise-based toasts: show a pending toast while a promise runs, then update to success or error automatically. This gives users immediate feedback without manual state juggling.
Conceptually, you call an API like toast.promise(promise, { loading, success, error }). sonner handles the lifecycle: it shows the loading toast, replaces or updates it upon resolution, and sets the final state to success or error.
Promise toasts simplify UX for network requests, batch jobs, or long-running computations. They reduce boilerplate and ensure consistent messaging across your app.
Customization: styling, positions, and actions
Sonner gives you flexible customization without forcing a CSS-in-JS solution. You can override classes or supply a custom component so your toasts match brand styles and interactive needs.
Typical customization surface includes: position (top-right, bottom-center), timeout duration, pause-on-hover behavior, and action buttons (undo, retry). Combine these with ARIA attributes to maintain accessibility.
When you implement custom toasts, separate visual markup from behavior. Keep the toast component presentational and use the sonner API or hooks to handle lifecycle and events—this keeps tests and styling isolated.
- Common features to enable: auto-dismiss, manual close, action callbacks, and toast queuing.
Example: pragmatic implementation
Below is a concise example showing provider setup, triggering a toast with a promise, and a custom action button. This pattern is production-ready: provider in root, hooks in components, and a thin adapter for promise/error handling.
// Root.jsx
import { Toaster } from 'sonner'
function Root() {
return (
<>
<App />
<Toaster position="top-right" />
>
)
}
// SaveButton.jsx
import { toast } from 'sonner'
function SaveButton({ onSave }) {
async function handleSave() {
const promise = onSave()
toast.promise(promise, {
loading: 'Saving...',
success: 'Saved successfully',
error: 'Save failed'
})
}
return <button onClick={handleSave}>Save</button>
}
Use the pattern above in forms, data grids, or background sync handlers. If your app uses optimistic updates, pair toasts with local state and reconcile when the network result arrives.
Best practices, accessibility, and performance
Notifications must be informative and unobtrusive. Avoid redundant toasts for every small state change—batch messages where appropriate. Reserve toasts for messages users need to be aware of but that don't require a modal interrupt.
Accessibility: ensure toasts announce via ARIA live regions (sonner handles this by default in many setups). Provide readable text, focusable action buttons, and keyboard operability for dismissing or acting on toasts.
Performance: because sonner is lightweight, it typically won't be the source of jank. Still, avoid creating toasts in tight loops or re-rendering the provider frequently. Keep the Toaster mounted once and reuse it.
- Use timestamped IDs or stable keys when tracking toasts triggered by async tasks.
Where to learn more & links
For an advanced walkthrough, see this practical sonner tutorial with patterns and code examples. It expands on promise handling, queuing, and real-world integration in React apps.
For the canonical library source and repo details, check the official sonner GitHub (installation, API, examples). The repo includes typed definitions and recommended usage patterns.
If you maintain visual consistency across multiple apps, consider creating a small wrapper around sonner to centralize styling, default durations, and message templates. That wrapper becomes the single place to update behavior across products.
Semantic core (expanded keyword set)
Grouped keywords for on-page SEO and internal linking. Use these naturally in copy and headings.
Primary:
- sonner
- React toast notifications
- React notification library
- sonner tutorial
- sonner installation
- sonner setup
- React toast hooks
- React toast library
Secondary:
- React alert notifications
- React toast messages
- sonner example
- sonner customization
- sonner promise
- React notification system
Clarifying / LSI:
- toast notifications React
- toast manager
- non-blocking alerts
- toast queue
- custom toast component
- auto-dismiss toast
- action button in toast
- ARIA live region toast
- toast update by id
FAQ
Install via npm or yarn (npm install sonner), then place <Toaster /> in your app root (e.g., App.jsx or _app.jsx). Use the exported hooks or toast functions to trigger notifications from components.
Yes. Use the promise helper (e.g., toast.promise(promise, { loading, success, error })). Sonner shows a loading toast while the promise is pending, then updates it on resolution for a consistent async UX.
Customize via props to Toaster (position, duration) or supply a custom toast component to match brand styles. Ensure accessibility by keeping readable content, ARIA live regions, and keyboard-focusable actions.
