> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendpost.io/llms.txt
> Use this file to discover all available pages before exploring further.

# React Quickstart

> Learn how to send emails with SendPost in your React application using hooks, forms, and API integration

## Prerequisites

To get the most out of this guide, you'll need to:

* [**Create a SendPost Account**](https://app.sendpost.io/register)
* [**React 18+**](https://react.dev/)
* A backend API endpoint (Next.js, Express, etc.) or direct API calls
* A **Sub-Account API Key** from your SendPost dashboard

<Info>
  You can find your API keys in your [SendPost Dashboard](https://app.sendpost.io). Make sure to use your Sub-Account API Key for sending emails.
</Info>

<Warning>
  **Security Note:** Never expose your SendPost API key in client-side React code. Always use a backend API endpoint to send emails. The examples below show both approaches, but prefer the backend approach for production.
</Warning>

## 1. Install Dependencies

```shellscript npm theme={null}
npm install axios
# Optional: if using SendPost SDK directly (not recommended for production)
npm install sendpost-js-sdk
```

## 2. Create Email Service Hook

Create `hooks/useEmail.js`:

```javascript JavaScript theme={null}
import { useState } from 'react';
import axios from 'axios';

const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:3000/api';

export function useEmail() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [success, setSuccess] = useState(false);

  const sendEmail = async (emailData) => {
    setLoading(true);
    setError(null);
    setSuccess(false);

    try {
      const response = await axios.post(`${API_BASE_URL}/send-email`, emailData);
      setSuccess(true);
      return { success: true, data: response.data };
    } catch (err) {
      const errorMessage = err.response?.data?.error || err.message || 'Failed to send email';
      setError(errorMessage);
      return { success: false, error: errorMessage };
    } finally {
      setLoading(false);
    }
  };

  const sendWelcomeEmail = async ({ email, firstName }) => {
    return sendEmail({
      to: email,
      subject: 'Welcome!',
      htmlBody: `
        <h1>Welcome, ${firstName}!</h1>
        <p>Thank you for joining us.</p>
        <p><a href="{{unsubscribe}}">Unsubscribe</a></p>
      `,
      groups: ['welcome'],
    });
  };

  const sendPasswordReset = async ({ email, resetToken, firstName }) => {
    const resetUrl = `${window.location.origin}/reset-password?token=${resetToken}`;
    return sendEmail({
      to: email,
      subject: 'Reset Your Password',
      htmlBody: `
        <h2>Hello ${firstName},</h2>
        <p>Click the link below to reset your password:</p>
        <p><a href="${resetUrl}">Reset Password</a></p>
        <p>This link will expire in 1 hour.</p>
      `,
      groups: ['password-reset'],
    });
  };

  return {
    sendEmail,
    sendWelcomeEmail,
    sendPasswordReset,
    loading,
    error,
    success,
  };
}
```

## 3. Contact Form Component

Create `components/ContactForm.jsx`:

```javascript JavaScript theme={null}
import React, { useState } from 'react';
import { useEmail } from '../hooks/useEmail';

export default function ContactForm() {
  const { sendEmail, loading, error, success } = useEmail();
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
  });

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const result = await sendEmail({
      to: 'contact@yourdomain.com',
      subject: `Contact from ${formData.name}`,
      htmlBody: `
        <h2>New Contact Form Submission</h2>
        <p><strong>Name:</strong> ${formData.name}</p>
        <p><strong>Email:</strong> ${formData.email}</p>
        <p><strong>Message:</strong></p>
        <p>${formData.message.replace(/\n/g, '<br>')}</p>
      `,
      textBody: `
        New Contact Form Submission
        
        Name: ${formData.name}
        Email: ${formData.email}
        Message: ${formData.message}
      `,
    });

    if (result.success) {
      setFormData({ name: '', email: '', message: '' });
    }
  };

  const handleChange = (e) => {
    setFormData({
      ...formData,
      [e.target.name]: e.target.value,
    });
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4 max-w-md mx-auto">
      <div>
        <label htmlFor="name" className="block text-sm font-medium mb-1">
          Name
        </label>
        <input
          type="text"
          id="name"
          name="name"
          value={formData.name}
          onChange={handleChange}
          required
          className="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-[#5750EC] focus:border-transparent"
        />
      </div>

      <div>
        <label htmlFor="email" className="block text-sm font-medium mb-1">
          Email
        </label>
        <input
          type="email"
          id="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
          required
          className="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-[#5750EC] focus:border-transparent"
        />
      </div>

      <div>
        <label htmlFor="message" className="block text-sm font-medium mb-1">
          Message
        </label>
        <textarea
          id="message"
          name="message"
          value={formData.message}
          onChange={handleChange}
          required
          rows={5}
          className="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-[#5750EC] focus:border-transparent"
        />
      </div>

      <button
        type="submit"
        disabled={loading}
        className="w-full px-6 py-2 bg-[#5750EC] text-white rounded-md hover:bg-[#4640D9] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
      >
        {loading ? 'Sending...' : 'Send Message'}
      </button>

      {error && (
        <div className="p-3 bg-red-50 border border-red-200 rounded-md text-red-700 text-sm">
          {error}
        </div>
      )}

      {success && (
        <div className="p-3 bg-green-50 border border-green-200 rounded-md text-green-700 text-sm">
          Message sent successfully!
        </div>
      )}
    </form>
  );
}
```

## 4. Welcome Email on User Registration

Create `components/RegistrationForm.jsx`:

```javascript JavaScript theme={null}
import React, { useState } from 'react';
import { useEmail } from '../hooks/useEmail';

export default function RegistrationForm() {
  const { sendWelcomeEmail, loading, error, success } = useEmail();
  const [formData, setFormData] = useState({
    firstName: '',
    lastName: '',
    email: '',
    password: '',
  });

  const handleSubmit = async (e) => {
    e.preventDefault();

    // First, register the user (your registration logic here)
    try {
      // Example: await registerUser(formData);
      
      // Then send welcome email
      const result = await sendWelcomeEmail({
        email: formData.email,
        firstName: formData.firstName,
      });

      if (result.success) {
        // Handle successful registration
        console.log('User registered and welcome email sent!');
      }
    } catch (err) {
      console.error('Registration error:', err);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      {/* Form fields */}
      <button type="submit" disabled={loading}>
        {loading ? 'Registering...' : 'Register'}
      </button>
      {error && <div className="text-red-600">{error}</div>}
      {success && <div className="text-green-600">Registration successful!</div>}
    </form>
  );
}
```

## 5. Password Reset Flow

Create `components/PasswordResetRequest.jsx`:

```javascript JavaScript theme={null}
import React, { useState } from 'react';
import { useEmail } from '../hooks/useEmail';

export default function PasswordResetRequest() {
  const { sendPasswordReset, loading, error, success } = useEmail();
  const [email, setEmail] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    // Generate reset token (your backend should handle this)
    const resetToken = await generateResetToken(email);

    const result = await sendPasswordReset({
      email,
      resetToken,
      firstName: 'User', // You might want to fetch this from your backend
    });

    if (result.success) {
      // Show success message
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label htmlFor="email" className="block text-sm font-medium mb-1">
          Email Address
        </label>
        <input
          type="email"
          id="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
          className="w-full px-4 py-2 border border-gray-300 rounded-md"
        />
      </div>

      <button
        type="submit"
        disabled={loading}
        className="w-full px-6 py-2 bg-[#5750EC] text-white rounded-md"
      >
        {loading ? 'Sending...' : 'Send Reset Link'}
      </button>

      {error && (
        <div className="p-3 bg-red-50 border border-red-200 rounded-md text-red-700">
          {error}
        </div>
      )}

      {success && (
        <div className="p-3 bg-green-50 border border-green-200 rounded-md text-green-700">
          Password reset link sent to your email!
        </div>
      )}
    </form>
  );
}
```

## 6. Using Context for Email Service

Create `context/EmailContext.jsx`:

```javascript JavaScript theme={null}
import React, { createContext, useContext } from 'react';
import { useEmail } from '../hooks/useEmail';

const EmailContext = createContext(null);

export function EmailProvider({ children }) {
  const emailService = useEmail();

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

export function useEmailContext() {
  const context = useContext(EmailContext);
  if (!context) {
    throw new Error('useEmailContext must be used within EmailProvider');
  }
  return context;
}
```

Use in your app:

```javascript JavaScript theme={null}
import { EmailProvider } from './context/EmailContext';

function App() {
  return (
    <EmailProvider>
      {/* Your app components */}
    </EmailProvider>
  );
}
```

## 7. Direct API Integration (Not Recommended for Production)

If you must use SendPost SDK directly in React (not recommended), create `services/sendpostClient.js`:

```javascript JavaScript theme={null}
import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();
const API_KEY = process.env.REACT_APP_SENDPOST_API_KEY; // ⚠️ Not secure!

export async function sendEmailDirect(emailData) {
  try {
    const emailMessage = new sendpost.EmailMessage();
    emailMessage.from = { email: 'hello@playwithsendpost.io' };
    emailMessage.to = [{ email: emailData.to }];
    emailMessage.subject = emailData.subject;
    emailMessage.htmlBody = emailData.htmlBody;
    emailMessage.textBody = emailData.textBody;

    const response = await emailApi.sendEmail(API_KEY, { emailMessage });
    return { success: true, messageId: response.messageId };
  } catch (error) {
    return { success: false, error: error.message };
  }
}
```

<Warning>
  **Never expose your API key in client-side code!** This example is for demonstration only. Always use a backend API endpoint in production.
</Warning>

## 8. Environment Variables

Create `.env` file:

```env theme={null}
REACT_APP_API_URL=http://localhost:3000/api
# DO NOT add SENDPOST_API_KEY here - use backend only!
```

## 9. Error Handling Best Practices

Create `utils/emailErrorHandler.js`:

```javascript JavaScript theme={null}
export function handleEmailError(error) {
  if (error.response) {
    // Server responded with error
    switch (error.response.status) {
      case 400:
        return 'Invalid email data. Please check your input.';
      case 401:
        return 'Authentication failed. Please check your API key.';
      case 429:
        return 'Too many requests. Please try again later.';
      case 500:
        return 'Server error. Please try again later.';
      default:
        return error.response.data?.error || 'An error occurred';
    }
  } else if (error.request) {
    // Request made but no response
    return 'Network error. Please check your connection.';
  } else {
    // Something else happened
    return error.message || 'An unexpected error occurred';
  }
}
```

Use in your hook:

```javascript JavaScript theme={null}
import { handleEmailError } from '../utils/emailErrorHandler';

// In your sendEmail function:
catch (err) {
  const errorMessage = handleEmailError(err);
  setError(errorMessage);
  return { success: false, error: errorMessage };
}
```

<Warning>
  Make sure your sender email domain is verified in your SendPost account before sending emails.
</Warning>

## 10. Next Steps

Explore more examples and use cases:

<Columns cols={3}>
  <Card title="React Documentation" icon="react" href="https://react.dev/">
    Learn more about React framework
  </Card>

  <Card title="SendPost JavaScript SDK" icon="npm" href="https://www.npmjs.com/package/sendpost-js-sdk">
    View the official SDK package on npm
  </Card>

  <Card title="Personalization Guide" icon="book" href="/api-reference/common-use-cases/personalisation-within-emails">
    Learn how to personalize emails with Handlebars templates
  </Card>
</Columns>
