Przejdź do treści

Jak zrobić formularz kontaktowy w React Native (i Expo), który wysyła e-maile

Formularz kontaktowy w React Native, który wysyła Ci każdą wiadomość e-mailem – ze stanem wysyłania, ochroną przed botami i bez backendu. Działa w Expo i w czystym React Native.

Zaktualizowano:

Film jest po angielsku; poniżej znajdziesz pełny samouczek krok po kroku.

Dodasz formularz kontaktowy do aplikacji w React Native albo Expo z pakietem @frontmail/react-native: provider, hook useSendEmail, który śledzi stan wysyłania, i gotowy komponent Turnstile przeciw botom. E-mail wychodzi przez Twoją własną skrzynkę.

Potrzebujesz: darmowego konta Frontmail, projektu w Expo lub React Native i około dziesięciu minut.

1. Podłącz skrzynkę i utwórz szablon

  1. Usługi e-mail → Dodaj usługę: podłącz Gmail, Outlook, SMTP albo dostawcę e-maili transakcyjnych, zaznacz Ustaw jako domyślną, Zweryfikuj i zapisz.
  2. Szablony → Z galerii → Formularz kontaktowy → Użyj szablonu. Parametry wymagane: name, email, message; opcjonalne: phone, topic.
  3. Skopiuj ID szablonu (tpl_…) z zakładki Kod.

2. Zezwól na aplikacje mobilne

  • Bezpieczeństwo → Aplikacje mobilne → Zezwól na aplikacje mobilne → Zapisz. Aplikacje nie wysyłają nagłówka Origin, więc bez tego przełącznika API odpowiada origin_not_allowed.
  • Szablon → Ustawienia → Ochrona → Wymagaj CAPTCHA (Turnstile). Aplikacja korzysta ze wspólnego widżetu Turnstile Frontmail; klucze Cloudflare nie są potrzebne.

3. Instalacja

npx expo install @frontmail/react-native @react-native-async-storage/async-storage react-native-webview

W czystym projekcie React Native użyj npm i z tymi samymi pakietami i uruchom npx pod-install.

4. Zbuduj formularz

import { useRef, useState } from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { FrontmailProvider, TurnstileWebView, useSendEmail, type TurnstileWebViewHandle } from '@frontmail/react-native';

const options = { publicKey: 'pk_…' }; // keep the object stable

export default function App() {
  return (
    <FrontmailProvider options={options}>
      <ContactForm />
    </FrontmailProvider>
  );
}

function ContactForm() {
  const { send, status, error } = useSendEmail(null, 'tpl_…'); // null = default service
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [message, setMessage] = useState('');
  const [token, setToken] = useState<string>();
  const turnstile = useRef<TurnstileWebViewHandle>(null);

  const onSend = async () => {
    await send({ name, email, message }, { turnstileToken: token });
    setToken(undefined);
    turnstile.current?.reset(); // a token works only once
  };

  if (status === 'sent' || status === 'held') return <Text>Thank you! We’ll get back to you soon.</Text>;

  return (
    <View style={{ gap: 12, padding: 16 }}>
      <TextInput placeholder="Name" value={name} onChangeText={setName} />
      <TextInput placeholder="Email" value={email} onChangeText={setEmail} keyboardType="email-address" autoCapitalize="none" />
      <TextInput placeholder="Message" value={message} onChangeText={setMessage} multiline />
      <TurnstileWebView ref={turnstile} onToken={setToken} />
      <Button title="Send" disabled={!token || status === 'sending'} onPress={onSend} />
      {error && <Text>{error.message}</Text>}
    </View>
  );
}

send nigdy nie rzuca wyjątku: zwraca wynik albo undefined, a status przechodzi z idle do sending, a potem do sent, held lub error. Ponowienia po błędach sieci używają jednego klucza idempotencji, więc użytkownik w pociągu nigdy nie wyśle Ci tej samej wiadomości dwa razy.

5. Przetestuj

Uruchom aplikację (npx expo start), wypełnij formularz i stuknij Send. E-mail trafi do Twojej skrzynki i do sekcji Historia w panelu.

  • origin_not_allowed – opcja Zezwól na aplikacje mobilne jest wyłączona albo niezapisana.
  • captcha_required – weryfikacja Turnstile jeszcze się nie zakończyła; przycisk pozostaje nieaktywny, dopóki nie ma tokenu.
  • invalid_template_params – wymagane pole jest puste albo e-mail jest nieprawidłowy.

held oznacza, że wiadomość została przyjęta, gdy kredyty były wyczerpane. Wyjdzie automatycznie, gdy tylko doładujesz konto – nic nie przepada.

Co dalej

  • Dodaj limitRate: { id: 'contact', throttle: 30_000 } do opcji providera, żeby pozwolić na jedną wiadomość na 30 sekund z jednego urządzenia.
  • Wyślij użytkownikowi potwierdzenie szablonem Automatyczna odpowiedź: dziękujemy za wiadomość z galerii.
Wszystkie samouczki