Sonner for React: Toast Notifications Tutorial & Examples
Sonner for React: Toast Notifications Tutorial & Examples
Quick take: Sonner is a tiny, pragmatic React toast library for unobtrusive notifications—this guide covers installation, basic usage, promise toasts, customization, hooks, accessibility, and production tips.
Why Sonner? A pragmatic overview
Sonner is deliberately minimal: it gives you a lightweight Toaster component, a concise API, and sensible defaults so you can ship notifications without wrestling with boilerplate. If you’ve used other React toast libraries, Sonner pares the surface area down to what you actually use in apps—push notifications, success/error states, and promise-based flows.
The value proposition is speed and clarity. Sonner’s API is designed so a single import and a tiny component add non-blocking toast messages to your UI. That makes it ideal for user feedback on async actions like saves, uploads, and network requests where a brief, ephemeral message does the job.
Because Sonner is composable, you can layer customization: change position, colors, durations, or swap in richer JSX toasts for actions. The examples below progress from installation to advanced patterns like toast.promise and custom renderers so you can adopt it incrementally.
Installation & setup (React)
Install Sonner from npm (or your package manager of choice). In most projects this is a one-line command that gets the package into your node_modules. Keep your React version up to date to avoid compatibility edge cases with hooks and concurrent rendering.
npm install sonner
# or
yarn add sonner
Once installed, mount the Toaster component at the top level of your app—typically inside App.jsx or a layout component—so it can render toasts from anywhere. The Toaster is passive: it doesn’t force layout changes and sits in the DOM ready to receive toast calls.
Example top-level setup (React):
import React from "react";
import { Toaster } from "sonner";
export default function App() {
return (
<>
<Toaster />
<MainRoutes />
>
);
}
Links: Sonner on npm and a practical walkthrough are helpful — see the official package page and a hands-on article: sonner on npm, and Advanced Toast Notifications with Sonner in React for extra patterns.
Basic usage: showing toasts and types
Once the Toaster is mounted, call the toast API from event handlers, effects, or utilities. The minimal call shows a message. Sonner also exposes convenience methods for common states so your UX is explicit: success, error, or info-style toasts.
import { toast } from "sonner";
// simple
toast("Saved");
// typed
toast.success("Saved successfully!");
toast.error("Save failed.");
Toast calls are non-blocking and return an id you can use to dismiss or update the message later. This is handy for crafting flows where an in-flight toast becomes success or error depending on the result of an async operation.
For example, you can store the id and call toast.dismiss(id) to remove it programmatically, or relying on the toaster’s auto-dismiss duration is also common for ephemeral messages that shouldn’t linger.
Advanced patterns: promise toasts, customizing, and hooks
One of the most powerful and ergonomic patterns is a promise-based toast: show a „loading” toast while a promise runs, then replace it with success or error. Sonner provides a promise helper to map promise states to messages—this reduces race conditions and keeps UI feedback in sync with background work.
// pattern (pseudocode—API maps to the library's toast.promise)
toast.promise(apiCall(), {
loading: "Uploading…",
success: "Upload complete!",
error: "Upload failed"
});
Customization goes two ways: API options and custom renderers. API-level props let you set position, duration, and global colors on the Toaster component; custom renderers let you render React nodes inside a toast if you need actions (undo buttons), progress bars, or richer markup for copyable links. Use custom JSX sparingly—keep toasts digestible.
For hook-centric patterns, encapsulate toast logic in small utilities. For example, create a useNotifier hook that returns bound functions like notifySuccess and notifyError. This keeps components focused on UI while centralizing toast behavior and styles for consistency across the app.
Customization checklist and examples
Practical customization touches include position, duration, color modes, and close-button behavior. These are usually configured on the Toaster and via options passed to individual toast calls when you need variance per message.
- Position: top-right, bottom, top-center depending on your UX pattern.
- Duration: short for confirmations, longer for actions requiring reading or copying.
- Rich content: include an inline action (like Undo) only when it directly relates to the toast.
Example: custom Toaster props and per-toast override:
<Toaster position="top-right" richColors />
// per toast
toast("Saved", { duration: 3000 });
toast.success("Deleted", { id: "delete-123", duration: 4000 });
Consistency is key: standardize on durations and positions in a design tokens file or a small theme wrapper to avoid a chaotic notification experience.
Accessibility and best practices
Toasts are transient, so make them accessible: ensure they announce via ARIA live regions and provide visible focusable alternatives for critical actions. Sonner typically renders toasts into the DOM so screen readers can pick them up, but verify ARIA attributes in the runtime and test with a screen reader.
Keep toast copy short and actionable. If the user must act, include an inline affordance (like Undo). If the toast only informs, prefer auto-dismiss and keep it off the screen longer than 500ms so motion-sensitive users have time to notice it.
Performance tip: avoid using large images or heavy components inside toasts. Treat them as micro-interactions that complement the primary UI rather than replace it.
Troubleshooting & common pitfalls
If toasts don’t appear, confirm the Toaster component is mounted and that the toast import comes from the same Sonner instance. Duplicate package installs (monorepos or mismatched versions) can cause multiple contexts where the Toaster and the toast caller don’t share runtime state—ensure a single copy of sonner in your dependency tree.
Race conditions can occur when you show then immediately dismiss toasts around route changes. Use the returned id from toast calls to coordinate explicit dismissals, and consider adding a small delay when navigating away from pages that trigger toasts.
When debugging style issues, inspect the generated DOM: most styling comes from small, scoped classes and inline styles from the library. Override responsibly with CSS variables or a theme wrapper rather than heavy specificity hacks.
Code snippets — practical examples
Below are concise, copy-paste-ready snippets you can adapt. They cover a save flow, a promise flow, and a custom action.
// Save button example
import { toast } from "sonner";
function SaveButton({ save }) {
async function onSave() {
try {
const id = toast("Saving…");
await save();
toast.success("Saved!", { id }); // replace or keep based on API
} catch (err) {
toast.error("Save failed.");
}
}
return <button onClick={onSave}>Save</button>;
}
// Promise toast example (recommended)
toast.promise(fetchData(), {
loading: "Fetching…",
success: "Loaded!",
error: "Unable to load"
});
// Custom toast with action
toast((t) => (
<div>
<strong>Uploaded</strong>
<button onClick={() => undoUpload()}>Undo</button>
</div>
));
SEO, voice search, and featured snippets
Write copy that answers common user questions in the first 40–60 words of your subsection to increase chances of being pulled into a featured snippet. For voice search, use conversational phrases and include short declarative answers—e.g., „To install Sonner, run npm install sonner”—so assistants can read concise instructions.
Include code examples formatted as code blocks and brief how-to steps at the top of tutorial pages; search engines often surface these as rich results for developer queries like „sonner installation” or „React promise toast.”
Backlinks and further reading
Useful, authoritative references to include from your project or docs:
- Advanced Toast Notifications with Sonner in React — practical walkthrough and examples.
- sonner (npm) — package page and installation commands.
- React documentation — for best practices on hooks and component structure.
Semantic core (keyword clusters)
Primary (high intent)
- sonner
- sonner tutorial
- sonner installation
- sonner setup
- sonner example
- sonner customization
- sonner promise
Secondary (product & intent-based)
- React toast notifications
- React notification library
- React toast messages
- React alert notifications
- React notification system
- React toast hooks
- React toast library
Clarifying / LSI phrases
- toaster component
- toast.promise
- toast.dismiss
- custom toast renderer
- position and duration
- ARIA live region for toasts
- non-blocking notifications
- undo action toast
- toast accessibility
Frequently Asked Questions (FAQ)
- How do I install and set up Sonner in a React project?
-
Install via npm or yarn: npm install sonner (or yarn add sonner). Import and mount the Toaster component near the root of your app—commonly inside App.jsx or a layout—so that any toast calls (imported toast) can render messages. Example: import { Toaster } from „sonner”; then include <Toaster /> in your JSX.
- What is toast.promise and how do I use it?
-
toast.promise maps a promise’s lifecycle to three messages (loading, success, error). Pass the promise and an object with those messages; Sonner will show loading, then replace it with success or error automatically. This pattern simplifies async UX for saves, uploads, and fetches.
- How do I customize Sonner toasts (style, duration, and actions)?
-
Configure global behavior via Toaster props (position, colors, etc.) and override per toast by passing options like duration or id. For richer content, render JSX inside a toast (custom renderer) and include inline buttons for actions such as Undo. Keep content concise and ensure accessible labels for interactive elements.