Пошук уроків, статей та іншого контенту
Навчіться підключати й обробляти значення текстових полів, списків вибору та багаторядкових полів у React.
input, select і textarea дають користувачу змогу вводити дані. У React їхні значення зазвичай зберігають у стані компонента.
Такий підхід називається керованими компонентами:
React зберігає поточне значення у стані.
Атрибут value передає це значення в поле.
Обробник onChange оновлює стан після кожної зміни.
Схема роботи виглядає так:
стан → value поля → введення користувача → onChange → оновлення стануinputДля текстового поля використовують
valueonChangeimport { useState } from "react";
function NameInput() {
const [name, setName] = useState("");
function handleChange(event) {
setName(event.target.value);
}
return (
<label>
Ім’я:
<input
type="text"
value={name}
onChange={handleChange}
/>
</label>
);
}event.target.value містить поточне значення поля.
Коротший варіант обробника:
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
/>Коли користувач вводить символ, React викликає onChange, а setName оновлює стан. Після цього компонент перемальовується з новим значенням.
Початкове значення задають під час створення стану:
const [name, setName] = useState("Олена");У такому разі поле спочатку міститиме текст Олена.
selectДля списку вибору застосовують той самий підхід:
import { useState } from "react";
function RoleSelect() {
const [role, setRole] = useState("");
return (
<label>
Роль:
<select
value={role}
onChange={(event) => setRole(event.target.value)}
>
<option value="">Оберіть роль</option>
<option value="frontend">Frontend-розробник</option>
<option value="backend">Backend-розробник</option>
<option value="designer">Дизайнер</option>
</select>
</label>
);
}Значенням стану буде значення атрибута value вибраного option:
"frontend";
"backend";
"designer";
"", якщо вибрано початковий пункт.
Текст між тегами option — це напис, який бачить користувач. Значення з value — це дані, які отримує програма.
Наприклад:
<option value="frontend">Frontend-розробник</option>Після вибору React отримає значення "frontend".
textareaУ React textarea також є керованим елементом:
import { useState } from "react";
function MessageInput() {
const [message, setMessage] = useState("");
return (
<label>
Повідомлення:
<textarea
value={message}
onChange={(event) => setMessage(event.target.value)}
rows={5}
placeholder="Введіть повідомлення"
/>
</label>
);
}На відміну від звичайного HTML, початковий текст textarea у React задають через value, а не через дочірній текст:
<textarea value={message} onChange={handleChange} />Не потрібно писати так:
<textarea onChange={handleChange}>
Початковий текст
</textarea>Якщо поле має бути керованим, його значення повинно надходити зі стану.
Усі поля можна об’єднати у форму. Під час надсилання форми браузер за замовчуванням перезавантажує сторінку, тому в React зазвичай викликають event.preventDefault().
import { useState } from "react";
export default function App() {
const [name, setName] = useState("");
const [role, setRole] = useState("");
const [message, setMessage] = useState("");
const [submittedData, setSubmittedData] = useState(null);
function handleSubmit(event) {
event.preventDefault();
setSubmittedData({
name,
role,
message,
});
}
return (
<main>
<h1>Форма контакту</h1>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Ім’я</label>
<input
id="name"
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Введіть ім’я"
required
/>
</div>
<div>
<label htmlFor="role">Роль</label>
<select
id="role"
value={role}
onChange={(event) => setRole(event.target.value)}
required
>
<option value="">Оберіть роль</option>
<option value="frontend">Frontend-розробник</option>
<option value="backend">Backend-розробник</option>
<option value="designer">Дизайнер</option>
</select>
</div>
<div>
<label htmlFor="message">Повідомлення</label>
<textarea
id="message"
value={message}
onChange={(event) => setMessage(event.target.value)}
placeholder="Напишіть повідомлення"
rows={5}
required
/>
</div>
<button type="submit">Надіслати</button>
</form>
{submittedData && (
<section>
<h2>Отримані дані</h2>
<p>Ім’я: {submittedData.name}</p>
<p>Роль: {submittedData.role}</p>
<p>Повідомлення: {submittedData.message}</p>
</section>
)}
</main>
);
}У цьому прикладі:
name зберігає значення input;
role зберігає значення select;
message зберігає значення textarea;
кожне поле оновлює власний стан через onChange;
handleSubmit отримує актуальні значення всіх полів;
event.preventDefault() не дозволяє браузеру перезавантажити сторінку;
required не дозволяє надіслати порожнє поле.
label і поляДля доступності пов’язуйте label з полем через htmlFor та id:
<label htmlFor="email">Електронна пошта</label>
<input id="email" type="email" />Значення htmlFor має збігатися зі значенням id. Клік по напису тоді активує відповідне поле.
Якщо поле вкладене всередину label, додатковий зв’язок через htmlFor не обов’язковий:
<label>
Ім’я
<input type="text" />
</label>Коли форма має багато текстових полів, їхній стан можна зберігати в одному об’єкті:
import { useState } from "react";
export default function App() {
const [form, setForm] = useState({
name: "",
city: "",
});
function handleChange(event) {
const { name, value } = event.target;
setForm((previousForm) => ({
...previousForm,
[name]: value,
}));
}
return (
<form>
<label>
Ім’я
<input
name="name"
value={form.name}
onChange={handleChange}
/>
</label>
<label>
Місто
<input
name="city"
value={form.city}
onChange={handleChange}
/>
</label>
<p>
{form.name} — {form.city}
</p>
</form>
);
}Властивість name визначає, яке поле об’єкта потрібно оновити:
const { name, value } = event.target;Для безпечного оновлення зберігають попередні властивості через spread-оператор:
setForm((previousForm) => ({
...previousForm,
[name]: value,
}));Без ...previousForm інші поля об’єкта могли б бути втрачені.
value, але не має onChange<input value={name} />Таке поле буде доступним лише для читання, оскільки React завжди встановлюватиме значення зі стану.
Потрібно додати обробник:
<input
value={name}
onChange={(event) => setName(event.target.value)}
/>defaultValue разом із керуванням через станdefaultValue задає лише початкове значення:
<input defaultValue="Олена" />Якщо значення має змінюватися через стан, використовуйте value:
<input
value={name}
onChange={(event) => setName(event.target.value)}
/>Не змішуйте ці два підходи для одного поля.
selectЯкщо стан починається з порожнього рядка, у списку має бути option з таким самим значенням:
const [role, setRole] = useState("");
<select value={role} onChange={handleChange}>
<option value="">Оберіть роль</option>
<option value="frontend">Frontend-розробник</option>
</select>event.preventDefault()Якщо не викликати event.preventDefault() у onSubmit, браузер може перезавантажити сторінку після надсилання форми.
function handleSubmit(event) {
event.preventDefault();
// Оброблення даних форми
}Для select потрібно читати event.target.value, а не текст елемента option:
function handleChange(event) {
setRole(event.target.value);
}Так стан міститиме стабільне програмне значення, наприклад "frontend".
input, select і textarea можна керувати через стан React.
Поточне значення передають у поле через value.
Зміни обробляють за допомогою onChange.
Нове значення отримують з event.target.value.
Для select значення визначає атрибут value вибраного option.
Для textarea у React використовують value, а не дочірній текст.
Дані форми обробляють у onSubmit.
event.preventDefault() запобігає перезавантаженню сторінки.
Якщо кілька полів мають спільний стан, їх зручно зберігати в одному об’єкті.