← Back to Demo Home

âš›ī¸ ModernToasts + React

Complete React integration examples with hooks and components

🚀 Live Demo

Try the React integration in action:

đŸ“Ļ Installation

npm install modern-toasts

đŸŽ¯ Basic Usage

Simple Import and Use

import toast from 'modern-toasts';

// In your component
function MyComponent() {
  const handleClick = () => {
    toast.success('Hello from React!');
  };

  return (
    <button onClick={handleClick}>
      Show Toast
    </button>
  );
}

đŸĒ Custom Hook

Create a reusable toast hook

// hooks/useToast.js
import toast from 'modern-toasts';
import { useCallback } from 'react';

export const useToast = () => {
  const showSuccess = useCallback((message, options) => {
    return toast.success(message, options);
  }, []);

  const showError = useCallback((message, options) => {
    return toast.error(message, options);
  }, []);

  const showInfo = useCallback((message, options) => {
    return toast.info(message, options);
  }, []);

  const showWarning = useCallback((message, options) => {
    return toast.warning(message, options);
  }, []);

  const dismiss = useCallback((id) => {
    toast.dismiss(id);
  }, []);

  const dismissAll = useCallback(() => {
    toast.dismissAll();
  }, []);

  return {
    showSuccess,
    showError,
    showInfo,
    showWarning,
    dismiss,
    dismissAll
  };
};

Using the hook in components

import { useToast } from './hooks/useToast';

function UserProfile() {
  const { showSuccess, showError } = useToast();

  const handleSave = async () => {
    try {
      await saveUserProfile();
      showSuccess('Profile saved successfully!');
    } catch (error) {
      showError('Failed to save profile. Please try again.');
    }
  };

  return (
    <button onClick={handleSave}>
      Save Profile
    </button>
  );
}

🎨 Toast Provider Component

Create a context-based toast system

// components/ToastProvider.jsx
import React, { createContext, useContext, useCallback } from 'react';
import toast from 'modern-toasts';

const ToastContext = createContext();

export const ToastProvider = ({ children, config = {} }) => {
  // Configure toast on mount
  React.useEffect(() => {
    toast.configure({
      position: 'bottom-right',
      maxVisibleStackToasts: 3,
      enableBorderAnimation: true,
      enableFillAnimation: true,
      ...config
    });
  }, [config]);

  const showToast = useCallback((type, message, options = {}) => {
    return toast[type](message, options);
  }, []);

  const value = {
    success: (msg, opts) => showToast('success', msg, opts),
    error: (msg, opts) => showToast('error', msg, opts),
    info: (msg, opts) => showToast('info', msg, opts),
    warning: (msg, opts) => showToast('warning', msg, opts),
    dismiss: toast.dismiss,
    dismissAll: toast.dismissAll,
    configure: toast.configure
  };

  return (
    <ToastContext.Provider value={value}>
      {children}
    </ToastContext.Provider>
  );
};

export const useToastContext = () => {
  const context = useContext(ToastContext);
  if (!context) {
    throw new Error('useToastContext must be used within ToastProvider');
  }
  return context;
};

App setup with provider

// App.jsx
import { ToastProvider } from './components/ToastProvider';

function App() {
  return (
    <ToastProvider config={{ position: 'top-right' }}>
      <div className="App">
        <Header />
        <Main />
        <Footer />
      </div>
    </ToastProvider>
  );
}

🔄 Real-world Examples

Form Validation

import { useToast } from './hooks/useToast';

function ContactForm() {
  const { showError, showSuccess } = useToast();
  const [formData, setFormData] = useState({});

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    // Validation
    if (!formData.email) {
      showError('Email is required');
      return;
    }
    
    if (!formData.message) {
      showError('Message is required');
      return;
    }

    try {
      await submitForm(formData);
      showSuccess('Message sent successfully!', {
        autoDismiss: 5000
      });
      setFormData({});
    } catch (error) {
      showError('Failed to send message. Please try again.');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
    </form>
  );
}

API Error Handling

import { useToast } from './hooks/useToast';

function DataFetcher() {
  const { showError, showInfo } = useToast();
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    showInfo('Loading data...', { autoDismiss: 2000 });

    try {
      const response = await fetch('/api/data');
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      const result = await response.json();
      setData(result);
      
    } catch (error) {
      if (error.name === 'AbortError') {
        showError('Request was cancelled');
      } else if (error.message.includes('404')) {
        showError('Data not found');
      } else if (error.message.includes('500')) {
        showError('Server error. Please try again later.');
      } else {
        showError('Network error. Check your connection.');
      }
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={fetchData} disabled={loading}>
        {loading ? 'Loading...' : 'Fetch Data'}
      </button>
    </div>
  );
}

User Actions with Feedback

import { useToast } from './hooks/useToast';

function UserActions() {
  const { showSuccess, showWarning, showInfo } = useToast();

  const handleLike = () => {
    showSuccess('â¤ī¸ Liked!', { autoDismiss: 2000 });
  };

  const handleShare = () => {
    navigator.clipboard.writeText(window.location.href);
    showInfo('🔗 Link copied to clipboard!');
  };

  const handleDelete = () => {
    showWarning('âš ī¸ This action cannot be undone!', {
      autoDismiss: 0, // Persistent warning
      showCloseButton: true
    });
  };

  return (
    <div>
      <button onClick={handleLike}>Like</button>
      <button onClick={handleShare}>Share</button>
      <button onClick={handleDelete}>Delete</button>
    </div>
  );
}

âš™ī¸ Advanced Configuration

// Configure globally in your app
toast.configure({
  position: 'bottom-right',
  maxVisibleStackToasts: 4,
  defaultDuration: 4000,
  enableBorderAnimation: true,
  enableFillAnimation: true,
  pauseBackgroundToastsOnHover: true,
  animationDirection: 'left-to-right',
  customCSS: `
    .toast-container {
      z-index: 9999;
    }
    .toast-custom {
      border-radius: 12px;
    }
  `
});

🎭 Custom Styling

// Custom styled toasts
const showCustomToast = () => {
  toast.success('Custom styled toast!', {
    backgroundColor: '#1f2937',
    textColor: '#f9fafb',
    borderColor: '#10b981',
    className: 'my-custom-toast',
    icon: '🚀',
    autoDismiss: 5000
  });
};

📱 TypeScript Support

// types/toast.ts
import { ToastType, ToastOptions } from 'modern-toasts';

interface CustomToastOptions extends ToastOptions {
  userId?: string;
  trackingId?: string;
}

export const useTypedToast = () => {
  const showSuccess = (
    message: string, 
    options?: CustomToastOptions
  ): string => {
    return toast.success(message, options);
  };

  // ... other methods

  return { showSuccess };
};

🔗 Useful Links