Работа с формами
Формы в React бывают контролируемые (controlled) и неконтролируемые (uncontrolled).
Контролируемые компоненты
Значение input хранится в состоянии React. Компонент полностью управляет полем:
function NameForm() {
const [name, setName] = useState('');
return (
<form>
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>Привет, {name}</p>
</form>
);
}
Плюсы: можно валидировать на лету, менять значение программно, форматировать ввод.
Несколько полей
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
console.log({ email, password });
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Пароль"
/>
<button type="submit">Войти</button>
</form>
);
}
Один обработчик на все поля
Если полей много — используй имя поля:
function Form() {
const [form, setForm] = useState({
name: '',
email: '',
age: '',
});
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = e.target;
setForm({ ...form, [name]: value });
}
return (
<form>
<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<input name="age" value={form.age} onChange={handleChange} />
</form>
);
}
Select
<select value={role} onChange={(e) => setRole(e.target.value)}>
<option value="user">Пользователь</option>
<option value="admin">Админ</option>
</select>
Checkbox
<input
type="checkbox"
checked={agreed}
onChange={(e) => setAgreed(e.target.checked)}
/>
Radio
<label>
<input
type="radio"
value="male"
checked={gender === 'male'}
onChange={(e) => setGender(e.target.value)}
/>
Мужской
</label>
<label>
<input
type="radio"
value="female"
checked={gender === 'female'}
onChange={(e) => setGender(e.target.value)}
/>
Женский
</label>
Textarea
<textarea value={bio} onChange={(e) => setBio(e.target.value)} />
В React textarea тоже контролируется через value.
Неконтролируемые компоненты
Значение хранится в DOM, доступ через ref:
import { useRef } from 'react';
function Form() {
const inputRef = useRef<HTMLInputElement>(null);
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
console.log(inputRef.current?.value);
}
return (
<form onSubmit={handleSubmit}>
<input ref={inputRef} defaultValue="" />
<button>Отправить</button>
</form>
);
}
Используй, когда значение нужно только при отправке, и не требуется валидация на лету.
Валидация
function Form() {
const [email, setEmail] = useState('');
const [error, setError] = useState('');
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!email.includes('@')) {
setError('Некорректный email');
return;
}
setError('');
// отправка
}
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
{error && <p className="error">{error}</p>}
<button>Отправить</button>
</form>
);
}
Итоги
- Контролируемые поля — через
valueиonChange - Один обработчик на много полей — через
name - Checkbox —
checkedиe.target.checked - Submit —
onSubmitиpreventDefault - Неконтролируемые — через
ref