ExpoStartup

Toast

A temporary notification component for displaying feedback to users.

Toast

The Toast component provides a non-intrusive way to display short feedback messages to users. It appears at the top of the screen and automatically disappears after a specified duration.

Features

  • Multiple Types: Support for success, error, info, and warning toast types
  • Customizable Duration: Control how long the toast appears
  • Animated Transitions: Smooth enter and exit animations
  • Theming Support: Automatically adapts to light/dark mode
  • Callback Support: Execute code when the toast disappears

Import

import Toast from '@/components/Toast';

Props

PropTypeDefaultDescription
messagestringRequiredThe message to display in the toast
type'success' | 'error' | 'info' | 'warning''info'The type of toast to display
durationnumber3000Time in milliseconds before the toast auto-hides
onHide() => voidCallback function called when toast is hidden
isVisiblebooleanRequiredControls the visibility of the toast

Usage Examples

Basic Toast

function Example() {
  const [visible, setVisible] = useState(false);
  
  const showToast = () => {
    setVisible(true);
  };
  
  const handleHide = () => {
    setVisible(false);
  };
  
  return (
    <View>
      <Button title="Show Toast" onPress={showToast} />
      <Toast 
        message="This is an info toast"
        isVisible={visible}
        onHide={handleHide}
      />
    </View>
  );
}

Different Toast Types

function ToastTypeExample() {
  const [toastConfig, setToastConfig] = useState({
    visible: false,
    message: '',
    type: 'info'
  });
  
  const showToast = (type, message) => {
    setToastConfig({
      visible: true,
      message,
      type
    });
  };
  
  const handleHide = () => {
    setToastConfig(prev => ({ ...prev, visible: false }));
  };
  
  return (
    <View className="p-4 space-y-4">
      <Button 
        title="Success Toast" 
        onPress={() => showToast('success', 'Operation completed successfully')} 
      />
      
      <Button 
        title="Error Toast" 
        onPress={() => showToast('error', 'Something went wrong')} 
      />
      
      <Button 
        title="Warning Toast" 
        onPress={() => showToast('warning', 'Proceed with caution')} 
      />
      
      <Button 
        title="Info Toast" 
        onPress={() => showToast('info', 'Here is some information')} 
      />
      
      <Toast 
        message={toastConfig.message}
        type={toastConfig.type}
        isVisible={toastConfig.visible}
        onHide={handleHide}
      />
    </View>
  );
}

Custom Duration Toast

function LongToastExample() {
  const [visible, setVisible] = useState(false);
  
  const showToast = () => {
    setVisible(true);
  };
  
  const handleHide = () => {
    setVisible(false);
  };
  
  return (
    <View>
      <Button title="Show Long Toast" onPress={showToast} />
      <Toast 
        message="This toast will stay visible for 10 seconds"
        isVisible={visible}
        duration={10000}
        onHide={handleHide}
      />
    </View>
  );
}

Toast Service Example

Creating a Toast service for your application:

// ToastContext.js
import React, { createContext, useState, useContext } from 'react';
import Toast from '../components/Toast';
 
const ToastContext = createContext({
  showToast: () => {},
});
 
export const ToastProvider = ({ children }) => {
  const [toast, setToast] = useState({
    visible: false,
    message: '',
    type: 'info',
    duration: 3000,
  });
 
  const showToast = (message, type = 'info', duration = 3000) => {
    setToast({
      visible: true,
      message,
      type,
      duration,
    });
  };
 
  const hideToast = () => {
    setToast(prev => ({ ...prev, visible: false }));
  };
 
  return (
    <ToastContext.Provider value={{ showToast }}>
      {children}
      <Toast
        message={toast.message}
        type={toast.type}
        duration={toast.duration}
        isVisible={toast.visible}
        onHide={hideToast}
      />
    </ToastContext.Provider>
  );
};
 
export const useToast = () => useContext(ToastContext);

Using the Toast service in your components:

// App.js
import { ToastProvider } from './ToastContext';
 
export default function App() {
  return (
    <ToastProvider>
      <RootNavigator />
    </ToastProvider>
  );
}
 
// SomeScreen.js
import { useToast } from './ToastContext';
 
function SomeScreen() {
  const { showToast } = useToast();
  
  const handleSave = async () => {
    try {
      await saveData();
      showToast('Data saved successfully', 'success');
    } catch (error) {
      showToast('Failed to save data', 'error');
    }
  };
  
  return (
    <View>
      <Button title="Save Data" onPress={handleSave} />
    </View>
  );
}

Form Submission Example

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [toastVisible, setToastVisible] = useState(false);
  const [toastMessage, setToastMessage] = useState('');
  const [toastType, setToastType] = useState('info');
  
  const handleSubmit = async () => {
    if (!email || !password) {
      setToastMessage('Please fill in all fields');
      setToastType('warning');
      setToastVisible(true);
      return;
    }
    
    try {
      // Simulate API call
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      if (email === 'test@example.com' && password === 'password') {
        setToastMessage('Login successful');
        setToastType('success');
        setToastVisible(true);
        // Navigate or perform other operations
      } else {
        setToastMessage('Invalid credentials');
        setToastType('error');
        setToastVisible(true);
      }
    } catch (error) {
      setToastMessage('An error occurred');
      setToastType('error');
      setToastVisible(true);
    }
  };
  
  return (
    <View className="p-4">
      <Input
        label="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
      />
      
      <Spacer size={16} />
      
      <Input
        label="Password"
        value={password}
        onChangeText={setPassword}
        isPassword={true}
      />
      
      <Spacer size={24} />
      
      <Button title="Log In" onPress={handleSubmit} />
      
      <Toast
        message={toastMessage}
        type={toastType}
        isVisible={toastVisible}
        onHide={() => setToastVisible(false)}
      />
    </View>
  );
}

Best Practices

Keep Messages Concise

Toast messages should be short and to the point:

// Good: Clear and concise
showToast('Profile updated successfully', 'success');
 
// Avoid: Too verbose
showToast('Your profile information has been successfully updated in our system and all changes have been saved to the database', 'success');

Use Appropriate Toast Types

Choose the right toast type for the message:

// Success: For positive confirmations
showToast('Item added to cart', 'success');
 
// Error: For failures and errors
showToast('Failed to connect to server', 'error');
 
// Warning: For potential issues
showToast('Low battery, connect charger', 'warning');
 
// Info: For neutral information
showToast('New version available', 'info');

Avoid Overusing Toasts

Only show toasts for important information:

// Good: Important feedback for user actions
function saveDocument() {
  try {
    // Save document
    showToast('Document saved', 'success');
  } catch (error) {
    showToast('Failed to save document', 'error');
  }
}
 
// Avoid: Unnecessary notifications
function onScreenFocus() {
  // Don't do this
  showToast('You are viewing the dashboard', 'info');
}

Implementation Details

The Toast component uses React Native's Animated API to create smooth slide-in and slide-out animations. It positions itself at the top of the screen using absolute positioning and has a high z-index to ensure it appears above other content.

The component uses a colored dot to indicate the toast type and automatically adapts its text and background colors based on the current theme using the useThemeColors hook.

When isVisible becomes true, the component animates in, waits for the specified duration, and then animates out. Once the exit animation completes, it calls the onHide callback, which typically updates the parent component's state to set isVisible to false.

Notes

  • Multiple toast messages will stack and may overlap if not managed properly
  • Toast animations are handled using React Native's Animated API for smooth performance
  • The component uses a colored indicator dot to differentiate between toast types
  • For a centralized toast system, consider implementing a context-based solution
  • When using with navigation, make sure to place the Toast component at the root level

On this page