react-hot-toast is a lightweight, customizable, and beautiful toast notification library for React applications. It provides a simple API with zero configuration needed, beautiful animations, and extensive customization options. This guide walks through setting up and creating toast notification systems using react-hot-toast with React, from installation to a working implementation. This is part 38 of a series on using react-hot-toast with React.
Prerequisites
Before you begin, make sure you have:
- Node.js version 14.0 or higher installed
- npm, yarn, or pnpm package manager
- A React project (version 16.8 or higher) or create-react-app setup
- Basic knowledge of React hooks (useState, useCallback)
- Familiarity with JavaScript/TypeScript
- Understanding of CSS for styling
Installation
Install react-hot-toast using your preferred package manager:
npm install react-hot-toast
Or with yarn:
yarn add react-hot-toast
Or with pnpm:
pnpm add react-hot-toast
After installation, your package.json should include:
{
"dependencies": {
"react-hot-toast": "^2.4.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
Project Setup
Set up the Toaster component in your main entry file or App component:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Toaster } from 'react-hot-toast';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
<Toaster />
</React.StrictMode>
);
Or add it to your App component:
// src/App.jsx
import React from 'react';
import { Toaster } from 'react-hot-toast';
import './App.css';
function App() {
return (
<div className="App">
<Toaster />
{/* Your app content */}
</div>
);
}
export default App;
First Example / Basic Usage
Let's create a simple toast notification component. Create a new file src/ToastExample.jsx:
// src/ToastExample.jsx
import React from 'react';
import toast from 'react-hot-toast';
function ToastExample() {
const showSuccess = () => {
toast.success('Operation completed successfully!');
};
const showError = () => {
toast.error('Something went wrong!');
};
const showInfo = () => {
toast('Here is some information.', {
icon: 'ℹ️'
});
};
const showLoading = () => {
toast.loading('Processing...');
};
return (
<div style={{ padding: '20px' }}>
<h2>Toast Notification Examples</h2>
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
<button onClick={showSuccess}>Success</button>
<button onClick={showError}>Error</button>
<button onClick={showInfo}>Info</button>
<button onClick={showLoading}>Loading</button>
</div>
</div>
);
}
export default ToastExample;
Update your App.jsx:
// src/App.jsx
import React from 'react';
import { Toaster } from 'react-hot-toast';
import ToastExample from './ToastExample';
import './App.css';
function App() {
return (
<div className="App">
<ToastExample />
<Toaster />
</div>
);
}
export default App;
This creates basic toast notifications that appear when you click the buttons and automatically disappear after a few seconds.
Understanding the Basics
react-hot-toast provides several key features:
- toast.success: Show a success toast
- toast.error: Show an error toast
- toast.loading: Show a loading toast
- toast.custom: Show a custom toast with JSX
- toast.promise: Handle promises with automatic loading/success/error states
- Toaster: Component that renders all toasts
- Positioning: Customizable toast positions
- Customization: Extensive styling and behavior options
Key concepts:
-
Toaster Component:
Toastermust be rendered in your app to display toasts -
Toast API: Use the
toastobject to show different types of toasts - Automatic Dismissal: Toasts automatically disappear after a set duration
- Positioning: Toasts can be positioned in different corners
- Customization: Toast appearance and behavior can be customized with options
Here's an example with custom options and promise handling:
// src/AdvancedToastExample.jsx
import React from 'react';
import toast from 'react-hot-toast';
function AdvancedToastExample() {
const showCustomToast = () => {
toast('Custom toast message', {
duration: 5000,
position: 'top-center',
style: {
border: '1px solid #713200',
padding: '16px',
color: '#713200',
},
icon: '👏',
});
};
const showPromiseToast = () => {
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve('Success!') : reject('Error!');
}, 2000);
});
toast.promise(myPromise, {
loading: 'Processing...',
success: 'Operation completed!',
error: 'Operation failed!',
});
};
const showCustomJSX = () => {
toast.custom((t) => (
<div
style={{
background: 'white',
padding: '16px',
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
opacity: t.visible ? 1 : 0,
transition: 'opacity 0.3s',
}}
>
<strong>Custom JSX Toast</strong>
<p>This is a custom toast with JSX content.</p>
<button onClick={() => toast.dismiss(t.id)}>Close</button>
</div>
));
};
return (
<div style={{ padding: '20px' }}>
<h2>Advanced Toast Examples</h2>
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
<button onClick={showCustomToast}>Custom Toast</button>
<button onClick={showPromiseToast}>Promise Toast</button>
<button onClick={showCustomJSX}>Custom JSX</button>
</div>
</div>
);
}
export default AdvancedToastExample;
Practical Example / Building Something Real
Let's build a comprehensive notification system with custom hooks and different notification patterns:
// src/hooks/useToastNotifications.js
import { useCallback } from 'react';
import toast from 'react-hot-toast';
export const useToastNotifications = () => {
const showSuccess = useCallback((message, options = {}) => {
toast.success(message, {
duration: 3000,
position: 'top-right',
...options
});
}, []);
const showError = useCallback((message, options = {}) => {
toast.error(message, {
duration: 5000,
position: 'top-right',
...options
});
}, []);
const showLoading = useCallback((message) => {
return toast.loading(message, {
position: 'top-right'
});
}, []);
const showPromise = useCallback((promise, messages) => {
return toast.promise(promise, messages, {
position: 'top-right'
});
}, []);
const dismiss = useCallback((toastId) => {
toast.dismiss(toastId);
}, []);
return {
showSuccess,
showError,
showLoading,
showPromise,
dismiss
};
};
Now create an advanced notification system component:
// src/AdvancedToastSystem.jsx
import React, { useState } from 'react';
import { useToastNotifications } from './hooks/useToastNotifications';
import toast from 'react-hot-toast';
function AdvancedToastSystem() {
const { showSuccess, showError, showLoading, showPromise, dismiss } = useToastNotifications();
const [formData, setFormData] = useState({
message: '',
type: 'success'
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
if (!formData.message) {
showError('Please enter a message.');
return;
}
switch (formData.type) {
case 'success':
showSuccess(formData.message);
break;
case 'error':
showError(formData.message);
break;
default:
showSuccess(formData.message);
}
setFormData({ message: '', type: 'success' });
};
const simulateApiCall = async () => {
const loadingId = showLoading('Processing your request...');
try {
await new Promise(resolve => setTimeout(resolve, 2000));
dismiss(loadingId);
showSuccess('Operation completed successfully!');
} catch (error) {
dismiss(loadingId);
showError('Failed to complete operation. Please try again.');
}
};
const handlePromiseOperation = () => {
const myPromise = fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) throw new Error('Network error');
return response.json();
});
showPromise(myPromise, {
loading: 'Loading data...',
success: 'Data loaded successfully!',
error: 'Failed to load data.'
});
};
const showCustomStyled = () => {
toast('Custom styled toast', {
style: {
border: '2px solid #007bff',
padding: '16px',
color: '#007bff',
borderRadius: '8px',
fontSize: '16px',
fontWeight: '500'
},
icon: '🎨',
duration: 4000
});
};
return (
<div style={{ padding: '20px', maxWidth: '600px', margin: '0 auto' }}>
<h1>Advanced Toast System</h1>
<form onSubmit={handleSubmit} style={{ marginBottom: '20px', padding: '20px', border: '1px solid #ddd', borderRadius: '8px' }}>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px', fontWeight: '500' }}>
Message *
</label>
<input
type="text"
name="message"
value={formData.message}
onChange={handleInputChange}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
boxSizing: 'border-box'
}}
required
/>
</div>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px', fontWeight: '500' }}>
Type
</label>
<select
name="type"
value={formData.type}
onChange={handleInputChange}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
boxSizing: 'border-box'
}}
>
<option value="success">Success</option>
<option value="error">Error</option>
</select>
</div>
<button
type="submit"
style={{
width: '100%',
padding: '10px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px'
}}
>
Show Toast
</button>
</form>
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
<button
onClick={simulateApiCall}
style={{
padding: '10px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Simulate API Call
</button>
<button
onClick={handlePromiseOperation}
style={{
padding: '10px',
backgroundColor: '#ffc107',
color: 'black',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Promise Operation
</button>
<button
onClick={showCustomStyled}
style={{
padding: '10px',
backgroundColor: '#6c757d',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Custom Styled Toast
</button>
</div>
</div>
);
}
export default AdvancedToastSystem;
Update your App.jsx with custom Toaster configuration:
// src/App.jsx
import React from 'react';
import { Toaster } from 'react-hot-toast';
import AdvancedToastSystem from './AdvancedToastSystem';
import './App.css';
function App() {
return (
<div className="App">
<AdvancedToastSystem />
<Toaster
position="top-right"
toastOptions={{
duration: 4000,
style: {
background: '#363636',
color: '#fff',
},
success: {
duration: 3000,
iconTheme: {
primary: '#4ade80',
secondary: '#fff',
},
},
error: {
duration: 5000,
iconTheme: {
primary: '#ef4444',
secondary: '#fff',
},
},
}}
/>
</div>
);
}
export default App;
Common Issues / Troubleshooting
Toasts not displaying: Ensure
Toastercomponent is rendered in your app. It should be placed at the root level, typically in your main App component or index file.Toasts appearing in wrong position: Use the
positionprop on theToastercomponent or pass it in toast options. Available positions include 'top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'.Toasts not auto-dismissing: Check the
durationoption. Set a duration in milliseconds (e.g., 3000 for 3 seconds). Setduration: Infinityfor persistent toasts.Custom styling not working: Use the
styleorclassNameoptions when calling toast functions. For global styles, usetoastOptionson theToastercomponent.Promise toasts not working: Make sure the promise is properly structured.
toast.promiseautomatically handles loading, success, and error states based on the promise outcome.Multiple toasts stacking: react-hot-toast handles multiple toasts automatically. They will stack based on the position setting. Use
toast.dismiss()to dismiss all toasts or pass a specific toast ID.
Next Steps
Now that you have an understanding of react-hot-toast:
- Explore advanced customization options and themes
- Learn about different toast positions and animations
- Implement toast queues and limits
- Add custom toast components with JSX
- Integrate with React Context for global toast management
- Learn about other toast libraries (notistack, react-toastify)
- Check the official repository: https://github.com/timolins/react-hot-toast
- Look for part 39 of this series for more advanced topics
Summary
You've successfully set up react-hot-toast in your React application and created a toast notification system with custom hooks, promise handling, and advanced features. react-hot-toast provides a lightweight, beautiful solution for displaying temporary messages with extensive customization options.
SEO Keywords
react-hot-toast
React toast notifications
react-hot-toast tutorial
React notification library
react-hot-toast installation
React toast messages
react-hot-toast example
React alert notifications
react-hot-toast setup
React toast hooks
react-hot-toast customization
React notification system
react-hot-toast promise
React toast library
react-hot-toast getting started

Top comments (0)