mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmWeb Frontendupdated 21 Sept 2026

react-toastify review

React-Toastify 11.1.0 combines a mounted `ToastContainer` with an imperative `toast()` API for React 18 and 19. It handles timed messages, promise state, manual updates, controlled progress, stacked queues, swipe dismissal, custom React content, and multiple containers. Version 11.1 adds a CSP nonce for its injected style tag, fixes dismissal event order and touch dragging, clamps deep stacked layouts, restores mobile width, and supplies ARIA values for progress bars. An unstyled export is available when the application owns all notification CSS.

Verdict

React-Toastify 11.1.0 installed in 1.3 seconds, occupied 9 MB, and added 12.6 KB gzipped in our sandbox, with bundled types and 0 audit findings. It earns that weight when a React 18 or 19 app needs promise updates, queues, stacking, or custom content; use a local live region or smaller toaster for a few simple messages.

We installed it

Lab card: what happened when we installed react-toastifyScreenshot of react-toastify documentation
Install✓ · 1.3s5 packages on disk · 9 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser12.6 KBgzipped (42.2 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does react-toastify install cleanly?

Yes. In a fresh container with an empty cache, npm install react-toastify finished in 1 seconds, leaving 5 packages and 9 MB on disk. npm audit reported no known vulnerabilities.

How much does react-toastify add to a browser bundle?

12.6 KB gzipped (42.2 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does react-toastify work with both ESM and CommonJS?

Yes. Both import 'react-toastify' and require('react-toastify') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does react-toastify include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

react-toastify or sonner: which should you use?

sonner: Use it for a more opinionated toaster with fewer configuration decisions. React-Toastify 11.1.0 installed in 1.3 seconds, occupied 9 MB, and added 12.6 KB gzipped in our sandbox, with bundled types and 0 audit findings.

When should you not use react-toastify?

Your project uses React 17 or older; version 11.1.0 declares only React and React DOM 18 or 19 as peers

API stability4/5The `ToastContainer` and `toast()` model remains recognizable across releases, with typed helpers for success, error, promise, loading, update, dismiss, progress, pause, and change events. Version 11.1 adds CSP nonce support and fixes behavior without replacing that model. Major upgrades still deserve a migration pass: v11 removed public hooks, SCSS and minimal CSS outputs, several styling props, and callback children while changing how the default stylesheet reaches the page.
Docs4/5The documentation site covers installation, positioning, styling, promises, manual updates, controlled progress, multiple containers, accessibility, animations, and major-version migration. Bundled declarations expose defaults for the 5,000 ms timer, focus loss, dragging, roles, themes, and hotkeys. Some version 11.1 facts are clearest in its release notes, including nonce handling, synchronous removed events, progress-bar ARIA values, and the styled entry's mount-time CSS injection.
Maintenance4/5npm published 11.1.0 on April 19, 2026, and GitHub records the matching repository push that day. The release adds CSP nonce support and fixes touch release, vertical drag, deep-stack scaling, mobile width, dismissal ordering, duplicate close callbacks, and progress-bar accessibility. GitHub currently reports 103 issues and pull requests combined, which is a sizable queue, but the release links its fixes to reported cases and supports current React 19 tooling.
Ecosystem5/5The npm endpoint counted 4,141,124 downloads for the week ending August 24, 2026, and GitHub reports 13,437 stars. Version 11.1 supports both React 18 and 19, ships CommonJS and ESM entries, bundles declarations, provides a separate unstyled export, and includes a notification-center add-on. Its runtime code has 1 direct dependency plus the 2 React peers, while the large installed base makes framework recipes and troubleshooting discussions easy to find.

Use it if

  • A React 18 or 19 app needs promise, loading, update, dismiss, and progress flows from one API
  • Notifications must be callable from ordinary modules as well as component event handlers
  • Stacking, queue limits, swipe gestures, RTL, or several independently positioned containers are required
  • Custom toast components need typed data and an application-specific close reason
Skip it if

Setup reality

Our React-Toastify 11.1.0 install completed in 1.3 seconds in a fresh Node 22 container. It left 5 packages occupying 9 MB, and npm audit reported 0 known vulnerabilities. The package was 612 KB unpacked with 1 direct dependency and 2 peer dependencies. It bundles TypeScript declarations and an exports map. CommonJS require() and ESM import both worked.

Install React and React DOM 18 or 19, then mount a client-side ToastContainer. The styled entry injects CSS when the container mounts in version 11.1, so a strict CSP must pass its nonce through the new nonce prop. react-toastify/unstyled avoids that style tag but leaves placement, transitions, progress, responsive layout, and every visual state to your CSS. Next.js App Router needs a use client wrapper.

Calls made before a container mounts wait in the shared store, which can conceal a missing container in tests. Defaults include a 5,000 ms timeout, top-right placement, light theme, pause on hover and window blur, touch dragging, and role alert. Alt+T focuses the first notification and Escape collapses a stack. Review those keyboard and announcement choices instead of assuming they match the rest of the app.

A container limit queues excess messages. toast.dismiss() removes visible items but does not empty that waiting queue; call toast.clearWaitingQueue() when both must go. Multiple containers need matching stable IDs on the container and each toast call. Unsubscribe toast.onChange listeners and unmount containers after tests because the store is global. Our esbuild import measured 42.2 KB minified and 12.6 KB gzipped, excluding the React peers.

Patterns

Mount one client-side notification outlet mount-container

'use client';
import { ToastContainer, toast } from 'react-toastify';

export function Notifications() {
  return <ToastContainer aria-label="Application notifications" />;
}
export const notifySaved = () => toast.success('Saved');

The 11.1 styled entry injects CSS at mount. Next.js App Router requires the client boundary shown here.

Set duration per message type status-variants

toast.info('Sync started');
toast.success('Profile saved', { autoClose: 2500 });
toast.warning('Storage is almost full');
toast.error('Upload failed', { autoClose: false });

The default timeout is 5,000 ms. `false` keeps the error visible until a person or code dismisses it.

Reflect one promise in a toast promise-status

await toast.promise<User, Error>(saveUser(), {
  pending: 'Saving user...',
  success: { render: ({ data }) => `Saved ${data.name}` },
  error: { render: ({ data }) => `Save failed: ${data.message}` },
});

`toast.promise` returns the original promise and passes its resolved or rejected value into the corresponding renderer.

Finish a manually controlled loading message loading-update

const id = toast.loading('Uploading...');
try {
  await uploadFile(file);
  toast.update(id, { render: 'Upload complete', type: 'success', isLoading: false, autoClose: 3000 });
} catch {
  toast.update(id, { render: 'Upload failed', type: 'error', isLoading: false, autoClose: false });
}

Reset `isLoading` and choose the next timer. Otherwise the updated content can retain loading behavior.

Give a persistent warning one ID deduplicate

const OFFLINE = 'offline';
if (!toast.isActive(OFFLINE)) {
  toast.error('You are offline', { toastId: OFFLINE, autoClose: false });
}

A stable `toastId` prevents duplicate store entries; `isActive` is useful when creation depends on current visibility.

Remove displayed and waiting messages clear-queue

toast.dismiss();
toast.clearWaitingQueue();

// Target one item:
toast.dismiss('offline');

A container limit creates a waiting queue. Dismissing visible toasts alone allows queued items to replace them.

Close custom content with a typed reason custom-content

import type { ToastContentProps } from 'react-toastify';
type Invite = { email: string };
function InviteToast({ data, closeToast }: ToastContentProps<Invite>) {
  return <div>Invite sent to {data.email}<button onClick={() => closeToast('undo')}>Undo</button></div>;
}
toast<Invite>(InviteToast, { data: { email: 'ada@example.com' } });

The string passed to `closeToast` reaches `onClose` as a reason, allowing code to distinguish Undo from ordinary dismissal.

Limit a dark stacked container to 3 items stacked-policy

<ToastContainer
  position="bottom-right"
  theme="dark"
  stacked
  newestOnTop
  limit={3}
  nonce={cspNonce}
  aria-label="Status messages"
/>

The nonce applies to the injected style tag. The fourth notification waits until a visible slot opens.

Route editor and global messages separately multiple-containers

<ToastContainer containerId="global" position="top-right" />
<ToastContainer containerId="editor" position="bottom-center" />

toast('Draft autosaved', { containerId: 'editor' });
toast.error('Session expired', { containerId: 'global' });

The toast's `containerId` must match a mounted outlet. A typo sends the message nowhere useful.

Drive progress from upload bytes manual-progress

const id = toast('Uploading...', { autoClose: false, progress: 0 });
upload.onProgress((loaded, total) => {
  toast.update(id, { progress: loaded / total });
});
upload.onComplete(() => toast.done(id));

Controlled progress ranges from 0 through 1. Version 11.1 exposes its current, minimum, and maximum values to assistive technology.

Observe and release the global subscription change-events

const unsubscribe = toast.onChange((item) => {
  console.log(item.id, item.status, item.reason);
});

// cleanup
unsubscribe();

Version 11.1 reports `removed` synchronously when `toast.dismiss()` runs. Always unsubscribe during teardown.

Bring every visual rule yourself unstyled-entry

import { ToastContainer, toast } from 'react-toastify/unstyled';
import './notifications.css';

<ToastContainer toastClassName="app-toast" />;
toast('Custom design system toast');

The unstyled export injects no default sheet. Your CSS must cover position, dimensions, transitions, progress, and mobile behavior.

Alternatives

PackageRegistryPick it when
sonnernpmUse it for a more opinionated toaster with fewer configuration decisions.
react-hot-toastnpmUse it for a compact React API with headless rendering access.
notistacknpmUse it for provider-based snackbar queues in applications already following Material UI patterns.
@radix-ui/react-toastnpmUse it when unstyled primitives are preferable and your team will build the store and policy.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.