Anfrageformular in React Native erstellen – Angebotsanfrage per E-Mail
Ein Anfrageformular für React Native und Expo mit Auswahl von Leistung, Budget und Termin, das Ihnen jede Anfrage per E-Mail schickt und sie dem Kunden automatisch bestätigt.
Aktualisiert:
In diesem Tutorial bauen Sie einen Bildschirm für Angebotsanfragen in React Native: Der Kunde wählt eine Leistung und ein Budget, ergänzt Termin und Beschreibung, und Sie erhalten eine strukturierte E-Mail. Eine automatische Antwort bestätigt dem Kunden die Anfrage.
Sie brauchen: ein kostenloses Frontmail-Konto, ein Expo- oder React-Native-Projekt und etwa fünfzehn Minuten.
1. Postfach verbinden und Vorlagen anlegen
- E-Mail-Dienste → Dienst hinzufügen: Verbinden Sie Ihr Postfach oder Ihren Anbieter, Als Standard festlegen, Prüfen & speichern.
- Vorlagen → Aus der Galerie → Angebotsanfrage (Kategorie Geschäftlich) → Vorlage verwenden.
- Aus der Galerie → Automatische Antwort: Danke für Ihre Nachricht → Vorlage
verwenden. Legen Sie Standardwerte für
company_nameundresponse_timefest und wählen Sie die Vorlage dann in der Anfragevorlage unter Einstellungen → Zustellung → Vorlage für automatische Antwort aus.
Parameter der Anfragevorlage: name, email, service, details (Pflicht) sowie phone,
company, budget, deadline (optional, Termin als YYYY-MM-DD). service und budget
akzeptieren nur die Werte auf dem Tab Parameter – verwenden Sie in der App dieselben
Zeichenketten. Das Codebeispiel nutzt die Werte der englischen Vorlage; eine auf Deutsch angelegte
Vorlage hat Website, Onlineshop, Mobile App, Beratung, Sonstiges und Unter 5.000 €,
5.000–20.000 €, 20.000–50.000 €, Über 50.000 €.
2. Mobile Apps erlauben und CAPTCHA aktivieren
- Sicherheit → Mobile Apps → Mobile Apps erlauben → Speichern.
- Anfragevorlage → Einstellungen → Schutz → CAPTCHA verlangen (Turnstile) – die App nutzt das gemeinsame Widget von Frontmail, keine Schlüssel nötig.
3. Installieren
npx expo install @frontmail/react-native @react-native-async-storage/async-storage react-native-webview
4. Formular bauen
Damit das Beispiel ohne zusätzliche Abhängigkeiten auskommt, sind die Auswahlmöglichkeiten einfache
Chip-Buttons und der Termin wird als YYYY-MM-DD eingetippt. Setzen Sie gern Ihre bevorzugten
Picker-Komponenten ein – es zählen nur die Werte, die Sie an send übergeben.
import { useRef, useState } from 'react';
import { Button, Pressable, Text, TextInput, View } from 'react-native';
import { FrontmailProvider, TurnstileWebView, useSendEmail, type TurnstileWebViewHandle } from '@frontmail/react-native';
const options = { publicKey: 'pk_…' };
const SERVICES = ['Website', 'E-shop', 'Mobile app', 'Consulting', 'Other'];
const BUDGETS = ['Under $5k', '$5k–20k', '$20k–50k', 'Over $50k'];
export default function App() {
return (
<FrontmailProvider options={options}>
<QuoteForm />
</FrontmailProvider>
);
}
function Choice({ values, value, onChange }: { values: string[]; value?: string; onChange(v?: string): void }) {
return (
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8 }}>
{values.map((v) => (
<Pressable key={v} onPress={() => onChange(v === value ? undefined : v)} accessibilityState={{ selected: v === value }}>
<Text style={{ padding: 8, borderWidth: 1, borderRadius: 16, fontWeight: v === value ? '700' : '400' }}>{v}</Text>
</Pressable>
))}
</View>
);
}
function QuoteForm() {
const { send, status, error } = useSendEmail(null, 'tpl_…');
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [service, setService] = useState<string | undefined>(SERVICES[0]);
const [budget, setBudget] = useState<string>();
const [deadline, setDeadline] = useState('');
const [details, setDetails] = useState('');
const [token, setToken] = useState<string>();
const turnstile = useRef<TurnstileWebViewHandle>(null);
const onSend = async () => {
await send({ name, email, service, budget, deadline, details }, { turnstileToken: token });
setToken(undefined);
turnstile.current?.reset(); // a token works only once
};
if (status === 'sent' || status === 'held') return <Text>Thanks! We’ve emailed you a confirmation.</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" />
<Text>What do you need?</Text>
<Choice values={SERVICES} value={service} onChange={setService} />
<Text>Budget (optional)</Text>
<Choice values={BUDGETS} value={budget} onChange={setBudget} />
<TextInput placeholder="Deadline (YYYY-MM-DD, optional)" value={deadline} onChangeText={setDeadline} />
<TextInput placeholder="Project details" value={details} onChangeText={setDetails} multiline />
<TurnstileWebView ref={turnstile} onToken={setToken} />
<Button title="Request a quote" disabled={!token || !service || status === 'sending'} onPress={onSend} />
{error && <Text>{error.message}</Text>}
</View>
);
}
Leere optionale Werte (kein Budget, leerer Termin) werden automatisch aus der E-Mail weggelassen.
5. Testen
Starten Sie die App und senden Sie eine Anfrage mit Ihrer eigenen E-Mail-Adresse. Sie erhalten die
Anfrage und die Bestätigung; beide erscheinen im Verlauf. Validierungsfehler kommen als
invalid_template_params zurück, das fehlerhafte Feld steht in error.details.
Eine Anfrage mit Bestätigung kostet zwei Credits. Sind die Credits aufgebraucht, werden Anfragen als
heldangenommen und nach dem Aufladen versendet – der Hook meldetstatus === 'held'.
Nächste Schritte
- Führen Sie eine Liste aller Interessenten: Aktivieren Sie Kontakte sammeln in den Einstellungen der Vorlage.
- Übergeben Sie
{ locale: 'de' }als zweites Argument vonsend, um eine Sprachvariante der Vorlage zu verwenden.


