React-Toastify: Highly Customizable Notifications
React-Toastify is a widely adopted library for adding highly customizable, non-blocking notifications, often called "toasts" or "snackbars," to React applications. The current stable version is 11.0.5. It maintains an active development cycle, frequently releasing patch and minor updates, with significant major versions (like v10 and v11) introducing substantial architectural changes and feature enhancements. Key differentiators include its ease of integration, comprehensive customization options allowing it to blend into any design system, full RTL support, intuitive swipe-to-close gestures, the ability to render React components within toasts, programmatic toast updates, and a configurable progress bar. Version 11 streamlined setup by automatically injecting its stylesheet, eliminating the need for manual CSS imports. Version 10 involved a significant internal rewrite, improving stability and fixing long-standing issues. It ships with TypeScript types, facilitating robust development.
Common errors
-
Toast is undefined || Uncaught TypeError: Cannot read properties of undefined (reading 'content')
cause This error often occurs when the `toast` function is called before the `ToastContainer` component has been mounted or if there's a hydration mismatch in SSR/SSG contexts, especially in older versions.fixEnsure `ToastContainer` is rendered and available in the DOM before `toast` calls are made. Upgrade to `react-toastify@^9.1.3` or newer, which partially addressed this issue. -
Memory leak when multiple containers are used
cause In versions prior to 9.0.7, having multiple `ToastContainer` instances could lead to memory leaks, especially when components unmounted.fixUpgrade to `react-toastify@^9.0.7` or newer. Ideally, limit your application to a single `ToastContainer` at the root for simpler state management and to avoid potential issues. -
CSS `translate` property not working correctly or invalid CSS
cause Prior to v9.1.2, there were issues with invalid CSS `translate` properties affecting toast positioning or animations.fixUpgrade to `react-toastify@^9.1.2` or newer, which contains a fix for invalid CSS translate issues. -
AutoClose doesn't work on update for toasts
cause In versions prior to 9.0.8, updating a toast would sometimes reset or disable the `autoClose` functionality, preventing toasts from automatically dismissing.fixUpgrade to `react-toastify@^9.0.8` or newer to resolve issues where `autoClose` might not work correctly after updating a toast.
Warnings
- breaking Starting from v11.0.0, importing the CSS stylesheet (`import 'react-toastify/dist/ReactToastify.css';`) is no longer required as the styles are automatically injected. Keeping the import will result in duplicate styles.
- breaking Version 10.0.0 involved a significant internal rewrite, which may have introduced subtle behavioral changes or require adjustments to highly customized implementations, particularly those relying on undocumented internal structures.
- gotcha Using multiple `ToastContainer` components in the same application can lead to unexpected behavior or issues if not managed carefully. While v9.0.7 fixed a specific memory leak, it's generally recommended to have a single `ToastContainer` at the root of your application.
- gotcha Older versions of `react-toastify` might not fully support React Server Components (RSC) as introduced in Next.js App Router. Support was explicitly added in v9.1.3.
Install
-
npm install react-toastify -
yarn add react-toastify -
pnpm add react-toastify
Imports
- ToastContainer
const ToastContainer = require('react-toastify').ToastContainer;import { ToastContainer } from 'react-toastify'; - toast
import toast from 'react-toastify/dist/toast'; // Deprecated path const toast = require('react-toastify').toast;import { toast } from 'react-toastify'; - ToastOptions
import { ToastOptions } from 'react-toastify'; // Incorrect for type-only import if using older TS or bundlersimport type { ToastOptions } from 'react-toastify';
Quickstart
import React, { useState } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css'; // Optional since v11, but good for backward compatibility
interface MyToastData {
username: string;
}
function App() {
const [username, setUsername] = useState('');
const notify = () => {
toast.info(`Hello ${username || 'Guest'}! Welcome.`, {
position: 'top-right',
autoClose: 3000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: 'light',
});
};
const promiseNotify = () => {
const myPromise = new Promise<MyToastData>((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve({ username: 'JaneDoe' });
} else {
reject({ err: 'Failed to fetch user' });
}
}, 2000);
});
toast.promise(myPromise, {
pending: 'Fetching user data...',
success: {
render({ data }) {
return `User ${data?.username} fetched successfully!`;
}
},
error: {
render({ data }) {
return `Error: ${data?.err}`;
}
}
}, { autoClose: 5000 });
};
return (
<div style={{ padding: '20px' }}>
<h1>React-Toastify Example</h1>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter your name"
style={{ marginRight: '10px', padding: '8px' }}
/>
<button onClick={notify} style={{ padding: '10px 15px', cursor: 'pointer' }}>Show Basic Toast</button>
<button onClick={promiseNotify} style={{ marginLeft: '10px', padding: '10px 15px', cursor: 'pointer' }}>Show Promise Toast</button>
<ToastContainer />
</div>
);
}
export default App;