SweetAlert2 is a beautiful, responsive, customizable, and accessible replacement for JavaScript's popup boxes. It provides a modern alternative to native browser alerts with extensive customization options, animations, and support for complex interactions like forms, file uploads, and async operations. This guide walks through advanced usage of SweetAlert2 with React, including custom configurations, React hooks integration, and complex dialog patterns. This is part 30 of a series on using SweetAlert2 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, useEffect, useCallback)
- Familiarity with async/await and Promises
- Understanding of CSS for custom styling
Installation
Install SweetAlert2 using your preferred package manager:
npm install sweetalert2
Or with yarn:
yarn add sweetalert2
Or with pnpm:
pnpm add sweetalert2
You may also want to install the React wrapper for better integration:
npm install @sweetalert2/with-react
After installation, your package.json should include:
{
"dependencies": {
"sweetalert2": "^11.0.0",
"@sweetalert2/with-react": "^5.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
Project Setup
Import SweetAlert2 styles in your main entry file or component:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'sweetalert2/src/sweetalert2.scss';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Or if using CSS instead of SCSS:
// src/index.js
import 'sweetalert2/dist/sweetalert2.min.css';
First Example / Basic Usage
Let's create a simple alert component. Create a new file src/AlertExample.jsx:
// src/AlertExample.jsx
import React from 'react';
import Swal from 'sweetalert2';
function AlertExample() {
const showSuccessAlert = () => {
Swal.fire({
title: 'Success!',
text: 'Operation completed successfully.',
icon: 'success',
confirmButtonText: 'OK'
});
};
const showErrorAlert = () => {
Swal.fire({
title: 'Error!',
text: 'Something went wrong.',
icon: 'error',
confirmButtonText: 'OK'
});
};
const showWarningAlert = () => {
Swal.fire({
title: 'Warning!',
text: 'Please review your input.',
icon: 'warning',
confirmButtonText: 'OK'
});
};
return (
<div style={{ padding: '20px' }}>
<h2>Basic SweetAlert2 Examples</h2>
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
<button onClick={showSuccessAlert}>Success Alert</button>
<button onClick={showErrorAlert}>Error Alert</button>
<button onClick={showWarningAlert}>Warning Alert</button>
</div>
</div>
);
}
export default AlertExample;
Understanding the Basics
SweetAlert2 provides several key features:
- Promise-based API: All alerts return promises that resolve with user actions
- Multiple button types: confirm, deny, cancel buttons
- Custom HTML: Full HTML support in alert content
- Input support: Text, email, password, number, select, radio, checkbox, file inputs
- Validation: Built-in and custom validation functions
- Animations: Customizable animations and transitions
- Theming: Extensive styling options
Key concepts for React integration:
- Async/Await: Use async/await for cleaner code with user interactions
- State Management: Integrate with React state for dynamic content
- Custom Hooks: Create reusable hooks for common alert patterns
- Error Handling: Proper error handling in async operations
Here's an example with confirmation dialogs:
// src/ConfirmationExample.jsx
import React from 'react';
import Swal from 'sweetalert2';
function ConfirmationExample() {
const handleDelete = async () => {
const result = await Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!',
cancelButtonText: 'Cancel'
});
if (result.isConfirmed) {
// Perform delete operation
await Swal.fire('Deleted!', 'Your item has been deleted.', 'success');
} else if (result.isDismissed) {
// User cancelled
Swal.fire('Cancelled', 'Your item is safe.', 'info');
}
};
const handleSave = async () => {
const result = await Swal.fire({
title: 'Do you want to save the changes?',
showDenyButton: true,
showCancelButton: true,
confirmButtonText: 'Save',
denyButtonText: "Don't save",
cancelButtonText: 'Cancel'
});
if (result.isConfirmed) {
// Save operation
await Swal.fire('Saved!', '', 'success');
} else if (result.isDenied) {
Swal.fire('Changes are not saved', '', 'info');
}
};
return (
<div style={{ padding: '20px' }}>
<h2>Confirmation Dialogs</h2>
<div style={{ display: 'flex', gap: '10px' }}>
<button onClick={handleDelete}>Delete Item</button>
<button onClick={handleSave}>Save Changes</button>
</div>
</div>
);
}
export default ConfirmationExample;
Practical Example / Building Something Real
Let's build a comprehensive form modal with validation, file upload, and async operations:
// src/AdvancedFormModal.jsx
import React, { useState, useCallback } from 'react';
import Swal from 'sweetalert2';
function AdvancedFormModal() {
const [isProcessing, setIsProcessing] = useState(false);
const showUserForm = useCallback(async () => {
const { value: formValues } = await Swal.fire({
title: 'Create New User',
html: `
<input id="swal-input1" class="swal2-input" placeholder="First Name" required>
<input id="swal-input2" class="swal2-input" placeholder="Last Name" required>
<input id="swal-input3" class="swal2-input" type="email" placeholder="Email" required>
<input id="swal-input4" class="swal2-input" type="tel" placeholder="Phone Number">
<select id="swal-input5" class="swal2-select">
<option value="">Select Role</option>
<option value="admin">Admin</option>
<option value="user">User</option>
<option value="guest">Guest</option>
</select>
`,
focusConfirm: false,
showCancelButton: true,
confirmButtonText: 'Create User',
cancelButtonText: 'Cancel',
preConfirm: () => {
const firstName = document.getElementById('swal-input1').value.trim();
const lastName = document.getElementById('swal-input2').value.trim();
const email = document.getElementById('swal-input3').value.trim();
const phone = document.getElementById('swal-input4').value.trim();
const role = document.getElementById('swal-input5').value;
// Validation
if (!firstName) {
Swal.showValidationMessage('First name is required');
return false;
}
if (!lastName) {
Swal.showValidationMessage('Last name is required');
return false;
}
if (!email) {
Swal.showValidationMessage('Email is required');
return false;
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
Swal.showValidationMessage('Please enter a valid email address');
return false;
}
if (!role) {
Swal.showValidationMessage('Please select a role');
return false;
}
return {
firstName,
lastName,
email,
phone,
role
};
},
didOpen: () => {
// Focus first input
document.getElementById('swal-input1').focus();
}
});
if (formValues) {
await handleCreateUser(formValues);
}
}, []);
const handleCreateUser = async (userData) => {
setIsProcessing(true);
// Show loading state
Swal.fire({
title: 'Creating user...',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
// Simulate success
await Swal.fire({
icon: 'success',
title: 'User Created!',
html: `
<p><strong>Name:</strong> ${userData.firstName} ${userData.lastName}</p>
<p><strong>Email:</strong> ${userData.email}</p>
<p><strong>Role:</strong> ${userData.role}</p>
`,
confirmButtonText: 'OK'
});
} catch (error) {
await Swal.fire({
icon: 'error',
title: 'Error',
text: 'Failed to create user. Please try again.',
confirmButtonText: 'OK'
});
} finally {
setIsProcessing(false);
}
};
const showFileUpload = useCallback(async () => {
const { value: file } = await Swal.fire({
title: 'Upload Profile Picture',
input: 'file',
inputAttributes: {
accept: 'image/*',
'aria-label': 'Upload your profile picture'
},
showCancelButton: true,
confirmButtonText: 'Upload',
cancelButtonText: 'Cancel'
});
if (file) {
const reader = new FileReader();
reader.onload = async (e) => {
await Swal.fire({
title: 'Preview',
imageUrl: e.target.result,
imageAlt: 'Uploaded picture',
showConfirmButton: true,
confirmButtonText: 'Use this image'
});
};
reader.readAsDataURL(file);
}
}, []);
const showAsyncOperation = useCallback(async () => {
let timerInterval;
const result = await Swal.fire({
title: 'Processing your request',
html: 'This will take a few seconds...',
timer: 5000,
timerProgressBar: true,
didOpen: () => {
Swal.showLoading();
const timer = Swal.getPopup().querySelector('b');
timerInterval = setInterval(() => {
timer.textContent = Swal.getTimerLeft();
}, 100);
},
willClose: () => {
clearInterval(timerInterval);
}
});
if (result.dismiss === Swal.DismissReason.timer) {
await Swal.fire({
icon: 'success',
title: 'Operation completed!',
text: 'Your request has been processed.',
confirmButtonText: 'OK'
});
}
}, []);
const showCustomStyled = useCallback(() => {
Swal.fire({
title: 'Custom Styled Alert',
text: 'This alert has custom styling',
icon: 'info',
customClass: {
popup: 'custom-popup',
title: 'custom-title',
confirmButton: 'custom-confirm-button'
},
buttonsStyling: false,
confirmButtonText: 'Got it!',
background: '#f0f0f0',
color: '#333'
});
}, []);
return (
<div style={{ padding: '20px' }}>
<h1>Advanced SweetAlert2 Examples</h1>
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', maxWidth: '300px' }}>
<button
onClick={showUserForm}
disabled={isProcessing}
style={{
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: isProcessing ? 'not-allowed' : 'pointer'
}}
>
Create User Form
</button>
<button
onClick={showFileUpload}
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Upload File
</button>
<button
onClick={showAsyncOperation}
style={{
padding: '10px 20px',
backgroundColor: '#ffc107',
color: 'black',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Async Operation
</button>
<button
onClick={showCustomStyled}
style={{
padding: '10px 20px',
backgroundColor: '#6c757d',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Custom Styled
</button>
</div>
</div>
);
}
export default AdvancedFormModal;
Now, create a custom React hook for reusable alert patterns:
// src/hooks/useSweetAlert.js
import { useCallback } from 'react';
import Swal from 'sweetalert2';
export const useSweetAlert = () => {
const showSuccess = useCallback((title, text = '') => {
return Swal.fire({
icon: 'success',
title,
text,
confirmButtonText: 'OK'
});
}, []);
const showError = useCallback((title, text = '') => {
return Swal.fire({
icon: 'error',
title,
text,
confirmButtonText: 'OK'
});
}, []);
const showConfirm = useCallback(async (options) => {
const result = await Swal.fire({
title: options.title || 'Are you sure?',
text: options.text || '',
icon: options.icon || 'warning',
showCancelButton: true,
confirmButtonColor: options.confirmColor || '#3085d6',
cancelButtonColor: options.cancelColor || '#d33',
confirmButtonText: options.confirmText || 'Yes',
cancelButtonText: options.cancelText || 'Cancel'
});
return result.isConfirmed;
}, []);
const showLoading = useCallback((title = 'Loading...') => {
Swal.fire({
title,
allowOutsideClick: false,
allowEscapeKey: false,
didOpen: () => {
Swal.showLoading();
}
});
}, []);
const closeAlert = useCallback(() => {
Swal.close();
}, []);
return {
showSuccess,
showError,
showConfirm,
showLoading,
closeAlert
};
};
Update your App.jsx:
// src/App.jsx
import React from 'react';
import AdvancedFormModal from './AdvancedFormModal';
import './App.css';
function App() {
return (
<div className="App">
<AdvancedFormModal />
</div>
);
}
export default App;
Add custom styles in App.css:
/* src/App.css */
.custom-popup {
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.custom-title {
font-size: 24px;
font-weight: 600;
color: #2c3e50;
}
.custom-confirm-button {
background-color: #007bff;
border-radius: 6px;
padding: 10px 24px;
font-weight: 500;
}
Common Issues / Troubleshooting
Styles not loading: Make sure you import SweetAlert2 styles in your entry file. Use
import 'sweetalert2/dist/sweetalert2.min.css'for CSS orimport 'sweetalert2/src/sweetalert2.scss'for SCSS.Promise handling: Always use
awaitor.then()when you need to handle user responses. SweetAlert2 methods return promises.Validation not working: Ensure
preConfirmreturnsfalseor callsSwal.showValidationMessage()for invalid inputs. Return the data object for valid inputs.Multiple alerts stacking: SweetAlert2 handles multiple alerts automatically, but you can prevent stacking by checking if an alert is already open using
Swal.isVisible().Custom HTML not rendering: Use the
htmlproperty instead oftextfor HTML content. Be careful with XSS vulnerabilities when using user-generated content.File upload issues: For file inputs, use the
input: 'file'option and handle the FileReader API for previews. Remember that file inputs return File objects, not strings.
Next Steps
Now that you have an advanced understanding of SweetAlert2:
- Explore advanced animations and transitions
- Learn about custom themes and styling
- Implement queue management for multiple alerts
- Add internationalization (i18n) support
- Integrate with React Context for global alert management
- Learn about other notification libraries (react-toastify, notistack)
- Check the official repository: https://github.com/sweetalert2/sweetalert2
- Look for part 31 of this series for more advanced topics
Summary
You've successfully integrated SweetAlert2 into your React application with advanced features including form validation, file uploads, async operations, and custom styling. SweetAlert2 provides a powerful, accessible alternative to native browser alerts with extensive customization options.
SEO Keywords
sweetalert2
React alert library
sweetalert2 tutorial
React modal dialogs
sweetalert2 installation
React confirmation dialogs
sweetalert2 example
React alert notifications
sweetalert2 forms
React custom alerts
sweetalert2 validation
React async alerts
sweetalert2 file upload
React alert hooks
sweetalert2 getting started
Top comments (0)