The toast is the most ignored piece of UI you will ever ship — until it is wrong. A notification that disappears in 800 milliseconds when your user needed 5 seconds, a stack of overlapping toasts that covers your modal’s close button, or a success message that renders during server-side rendering and crashes the page: every team with a React app has hit at least one of these. The three libraries that dominate the space — sonner (12,880 stars), react-hot-toast (10,969 stars), and react-toastify (13,436 stars) — all solve “show a message” but diverge sharply on customization, bundle size, and maintenance, and the differences decide which one survives contact with a real product.

Quick Verdict: Which Toast Library Should You Use?

For a new app in 2026, choose sonner. It has the cleanest API, the best visual design out of the box, a first-class promise API for async operations, and the most active maintenance (last push August 2026). If you need the absolute smallest footprint or a headless hook you can style yourself, choose react-hot-toast — it is under 5 kB and its useToaster hook gives you the rendering control with none of the styles. If you are maintaining a legacy codebase that needs battle-tested features like transitions, stacking, and multi-position support, react-toastify is the safe, boring choice — it has been around the longest and its feature list is the deepest, though it is also the heaviest. All three are MIT-licensed; do not migrate an existing app just for star counts.

Head-to-Head: Feature Comparison

Featuresonnerreact-hot-toastreact-toastify
GitHub stars (Aug 2026)12,88010,96913,436
Last push2026-08-102025-08-162026-04-19
Bundle size (min+gzip)~4 kB< 5 kB (incl. styles)~13 kB
Headless / unstyled APINoYes (useToaster)No
Promise API (toast.promise)YesYesYes
Rich colors / themesYes (light, dark, richColors)Via CSS onlyYes (light, dark, colored)
Keyboard shortcut supportYesNoNo
Swipe / drag to dismissYesYesYes (draggable)
Transitions (slide/bounce/zoom/flip)Built-in + customCSS-based4 built-in transitions
Toast stacking & limitsYesYesYes (limit, stacked)
React Server Components safeYesManualManual
LicenseMITMITMIT

The star counts are remarkably close; the differentiators are maintenance velocity, bundle cost, and how much styling control each one hands you.

Decision Matrix: Match the Library to Your Use Case

Use CaseRecommended LibraryWhy
Greenfield React app, want great defaultssonnerBest-looking toasts with zero config; active maintenance
Design system with custom toast markupreact-hot-toastHeadless useToaster hook; you own every pixel
Legacy app on React 16-18 with complex flowsreact-toastifyDeepest feature set, most battle-tested over a decade
Async upload / save flows with progress statessonner or react-toastifyBoth have polished toast.promise and loading states
Server-rendered Next.js appsonnerRSC-safe; other libraries need client-component guards
Strict bundle budget (< 6 kB)react-hot-toastSmallest footprint of the three
Toasts must be keyboard-accessiblesonnerBuilt-in keyboard shortcut and focus management

sonner: The Modern Default

sonner, built by the creator of the Radix UI-adjacent ecosystem (Emil Kowalski), is the youngest of the three and the one with the strongest design opinion. Its README is a study in minimalism: install, drop <Toaster /> in your app, call toast() from anywhere:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { Toaster, toast } from 'sonner';

function App() {
  return (
    <div>
      <Toaster />
      <button onClick={() => toast('My first toast')}>Give me a toast</button>
    </div>
  );
}

What you get beyond that line: toast.success() / toast.error() / toast.loading(), a promise API that swaps a loading spinner into a success or error state automatically, richColors for semantic coloring, light and dark themes, swipe-to-dismiss, and even a keyboard shortcut to dismiss the current toast. Because the component and the imperative API are decoupled, you can trigger toasts from anywhere in your tree — including outside React components. sonner is also the only one of the three that is safe to use in React Server Components without extra guarding, which makes it the natural default for Next.js codebases. The trade-off: you customize via component props rather than a full headless API, so heavily branded toast designs will fight its opinions.

react-hot-toast: The Lightweight Headless Option

react-hot-toast markets itself as “smoking hot notifications” with a hard constraint: less than 5 kB including styles. Its headline feature is the headless useToaster() hook — instead of shipping a <Toaster /> component with fixed markup, it gives you the toast state and lets you render whatever DOM you want. For most apps the built-in component is enough:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import toast, { Toaster } from 'react-hot-toast';

const notify = () => toast('Here is your toast.');

const App = () => {
  return (
    <div>
      <button onClick={notify}>Make me a toast</button>
      <Toaster />
    </div>
  );
};

The promise API (toast.promise(myPromise, {...})) renders automatic loading, success, and error states, and the library is accessible out of the box. The caveat is maintenance: the last push to timolins/react-hot-toast was August 2025, so the project has been quiet for roughly a year while React 19 and server components matured around it. It still works fine on React 18 and 19, but teams betting on long-term evolution should weigh that silence — the same single-maintainer risk we flagged in our React component libraries comparison.

react-toastify: The Battle-Tested Workhorse

react-toastify is the oldest and most feature-complete of the three, and it shows: transitions (Slide, Bounce, Zoom, Flip), draggable toasts, limit and stacked modes, newestOnTop, pauseOnHover, RTL support, and a dark/colored theme system. The core usage has stayed stable for years:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { ToastContainer, toast } from 'react-toastify';

function App(){
  const notify = () => toast("Wow so easy!");

  return (
    <div>
      <button onClick={notify}>Notify!</button>
      <ToastContainer />
    </div>
  );
}

Its toast.promise handles multi-step async flows, toast.dismiss() gives you programmatic control, and toast.update() lets you mutate an active toast (change a loading toast into an error toast with a retry button, for example). The costs: it is the heaviest of the three at roughly 13 kB gzipped, and its styling is built on CSS-in-JS under the hood, which pulls styled-components-style runtime into your bundle if you are not already using it — a decision we dissect in our CSS-in-JS libraries comparison. If you need maximum control and are not budget-constrained, this is the safe decade-proven pick.

Pitfalls: What Nobody Tells You About Toast Libraries

  1. Auto-dismiss timing is a UX decision, not a default. An 800 ms default is right for a “copied” confirmation and wrong for an error that must be read. sonner and react-toastify let you set duration per toast; react-hot-toast uses duration on the toast options. Audit your error paths and set explicit durations — the default is tuned for success messages.
  2. Z-index wars with modals and drawers. Toasts rendered inside the document flow can slide under modals with higher z-index. All three libraries let you configure the container’s z-index (sonner Toaster prop, react-toastify toastContainer class, react-hot-toast toastOptions), but teams routinely forget until a production report arrives. Decide one z-index tier for all overlay surfaces at the design-system level.
  3. SSR crashes and hydration mismatches. If toast() executes during server render — or your <Toaster /> renders in a server component that calls browser APIs — you get a crash or a hydration mismatch. sonner is RSC-safe; with the other two, wrap the container in a client component and defer any toast call to an effect or event handler.
  4. Promise API error handling is where bugs hide. toast.promise(p, {success, error}) swallows the rejection if you do not also .catch() it, which can leave unhandled rejections in your console and your error tracker. Always chain .catch() even when the toast shows the error UI.
  5. Stacking limits change user perception. If a process fires 20 toasts at once (batch import, sync events), an unconstrained container turns into a wall of overlapping boxes. Set limit (react-toastify) or the equivalent cap in the others, or debounce the source — toasts should report state, not narrate every event.
  6. Testing toasts is harder than testing buttons. Toasts are imperative and ephemeral, so Playwright tests often race them. Assert on the toast container’s presence with a data-testid (sonner supports toastOptions and the container is queryable in all three) and use fixed durations in test mode so toasts do not vanish mid-assertion.
  7. Bundle-size regression is silent. react-toastify’s CSS-in-JS runtime and react-hot-toast’s styles only become visible in your chunk graph. After switching, run webpack-bundle-analyzer and confirm the toast library does not push your route’s critical bundle past budget.

FAQ

By GitHub stars the three leaders are nearly tied: react-toastify at ~13,436, sonner at ~12,880, and react-hot-toast at ~10,969. Maintenance activity differs more than star counts — sonner had the most recent release activity (August 2026), while react-hot-toast has been quiet since August 2025.

Is sonner better than react-hot-toast?

For most new projects, yes: sonner has a more polished default design, rich colors and themes, keyboard shortcuts, React Server Components support, and active maintenance. react-hot-toast remains the better choice only when you want its headless useToaster API or the absolute smallest bundle.

Does react-toastify still work with React 19?

Yes. react-toastify is compatible with React 16.8 through 19 and its API (toast(), ToastContainer, toast.promise, toast.update) has been stable for years. It is the safest choice for legacy codebases precisely because of that stability.

How do I make toasts accessible?

Ensure your toast container renders with the appropriate live region semantics (role status for neutral messages, role alert for errors) and that auto-dismissed toasts give users time to read them — the Web Content Accessibility Guidelines recommend users be able to pause or extend notifications. sonner’s built-in focus management and keyboard dismissal are a strong default here.

Can I use these toast libraries in Next.js?

Yes, with a caveat: wrap the toast container in a client component ("use client") and never call toast() during module evaluation or server render. sonner is the most convenient for Next.js because it is safe in server components out of the box.

What is the smallest toast library for React?

react-hot-toast is the smallest of the three at under 5 kB including styles; sonner is close at roughly 4 kB for the core. react-toastify is the heaviest at around 13 kB gzipped due to its transition and theme system.


💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com