Ako vytvoriť dopytový formulár v React Native
Dopytový formulár v React Native a Expo s výberom služby, rozpočtu a termínu, ktorý vám každý dopyt pošle e-mailom a zákazníkovi ho automaticky potvrdí.
Aktualizované:
V tomto návode vytvoríte obrazovku na dopyt v React Native: zákazník vyberie službu a rozpočet, doplní termín a popis a vy dostanete štruktúrovaný e-mail. Automatická odpoveď zákazníkovi potvrdí prijatie dopytu.
Potrebujete: bezplatný účet Frontmail, projekt v Expo alebo React Native a zhruba pätnásť minút.
1. Pripojte schránku a vytvorte šablóny
- E-mailové služby → Pridať službu: pripojte svoju schránku alebo poskytovateľa, Nastaviť ako predvolenú, Overiť a uložiť.
- Šablóny → Z galérie → Dopyt (kategória Biznis) → Použiť šablónu.
- Z galérie → Automatická odpoveď: ďakujeme za správu → Použiť šablónu. Nastavte
predvolené hodnoty pre
company_namearesponse_timea potom ju vyberte v šablóne dopytu v Nastavenia → Doručovanie → Šablóna automatickej odpovede.
Parametre šablóny dopytu: name, email, service, details (povinné) a phone, company,
budget, deadline (nepovinné, termín ako YYYY-MM-DD). service a budget prijímajú iba
hodnoty uvedené na karte Parametre. Príklad kódu používa hodnoty anglickej šablóny; keď
šablónu vytvoríte v slovenčine, hodnoty budú slovenské (Web, E-shop, Mobilná aplikácia,
Konzultácie, Iné a Do 5 000 €, 5 000 – 20 000 €, 20 000 – 50 000 €, Nad 50 000 €) – v aplikácii
posielajte presne tie isté reťazce.
2. Povoľte mobilné aplikácie a zapnite CAPTCHA
- Zabezpečenie → Mobilné aplikácie → Povoliť mobilné aplikácie → Uložiť.
- Šablóna dopytu → Nastavenia → Ochrana → Vyžadovať CAPTCHA (Turnstile) – aplikácia používa zdieľaný widget Frontmailu, žiadne kľúče nepotrebujete.
3. Inštalácia
npx expo install @frontmail/react-native @react-native-async-storage/async-storage react-native-webview
4. Vytvorte formulár
Aby príklad nepotreboval ďalšie závislosti, výber je riešený jednoduchými tlačidlami (chipmi)
a termín sa zadáva ako YYYY-MM-DD. Pokojne použite svoje obľúbené komponenty na výber – záleží
iba na hodnotách, ktoré odovzdáte do send.
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>
);
}
Prázdne nepovinné hodnoty (bez rozpočtu, prázdny termín) sa z e-mailu automaticky vynechajú.
5. Vyskúšajte to
Spustite aplikáciu a odošlite dopyt s vlastným e-mailom. Dostanete dopyt aj potvrdenie; oba sa
zobrazia v História. Chyby validácie sa vrátia ako invalid_template_params a pole, ktoré
neprešlo, nájdete v error.details.
Dopyt s potvrdením stojí dva kredity. Keď kredity dôjdu, dopyty sa prijmú so stavom
helda po dobití sa odošlú – hook hlásistatus === 'held'.
Ďalšie kroky
- Majte prehľad o všetkých, ktorí žiadali o ponuku: v nastaveniach šablóny zapnite Zber kontaktov.
- Odovzdajte
{ locale: 'de' }ako druhý argument funkciesenda použije sa jazyková verzia šablóny.


