React
Beginner
1 min read
Form Submission and Async Validation
Example
import { useState, useEffect } from 'react';
function UniqueUsernameForm() {
const [username, setUsername] = useState('');
const [usernameError, setUsernameError] = useState('');
const [status, setStatus] = useState('idle'); // idle | checking | available | taken
// Debounced availability check
useEffect(() => {
if (username.length < 3) { setStatus('idle'); return; }
setStatus('checking');
const timer = setTimeout(async () => {
const res = await fetch(`/api/check-username?q=${username}`);
const data = await res.json();
setStatus(data.available ? 'available' : 'taken');
setUsernameError(data.available ? '' : 'Username is taken');
}, 400);
return () => clearTimeout(timer);
}, [username]);
const [submitStatus, setSubmitStatus] = useState('idle');
async function handleSubmit(e) {
e.preventDefault();
if (status !== 'available') return;
setSubmitStatus('loading');
try {
await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username }),
});
setSubmitStatus('success');
} catch {
setSubmitStatus('error');
}
}
return (
<form onSubmit={handleSubmit}>
<input
value={username}
onChange={e => setUsername(e.target.value)}
placeholder="Choose a username"
/>
{status === 'checking' && <span>Checking…</span>}
{status === 'available' && <span style={{ color: 'green' }}>Available!</span>}
{usernameError && <span style={{ color: 'red' }}>{usernameError}</span>}
<button type="submit" disabled={status !== 'available' || submitStatus === 'loading'}>
{submitStatus === 'loading' ? 'Registering…' : 'Register'}
</button>
{submitStatus === 'success' && <p>Done!</p>}
</form>
);
}