<input>
Вбудований компонент браузера <input>
компонента дозволяє відображати різні типи введень у формі.
<input />
Довідник
<input>
Щоб відобразити вхідні дані, відрендерити вбудований у браузер компонент <input>
.
<input name="myInput" />
Дивіться більше прикладів нижче.
Пропси
<input>
підтримує всі пропси спільних елементів.
Розширення React для пропсу formAction
наразі доступні лише в Canary та експериментальних каналах React. У стабільних випусках React formAction
працює лише як вбудований HTML-компонент браузера. Дізнайтеся більше про канали випуску React тут.
formAction
: Рядок або функція. Перевизначає батьківський <form action>
для type="submit"
і type="image"
. При передачі URL до action
форма поводитиметься як стандартна HTML-форма. Коли функція передається в formAction
, вона буде обробляти відправку форми. Дивіться <form action>
.
Ви можете зробити вхід контрольованим шляхом передачі одного з цих пропсів:
checked
: Логічний вираз. Для прапорця або перемикача, контролює, чи він вибраний.value
: Рядок. Для текстового введення керує його текстом. (Для перемикача - визначає дані його форми) .
Коли ви передаєте будь-який з них, ви також повинні передати обробник onChange
, який оновлює передане значення.
Ці пропси <input>
актуальні лише для неконтрольованих входів:
defaultChecked
: Логічний вираз. Визначає початкове значення для входівtype="checkbox"
таtype="radio"
.defaultValue
: Рядок. Вказує початкове значення для текстового введення.
Ці <input>
пропси актуальні як для неконтрольованих, так і для контрольованих входів:
accept
: Рядок. Вказує, які типи файлів приймаються вхідними данимиtype="file"
.alt
: Рядок. Вказує альтернативний текст зображення для вхідних данихtype="image"
.capture
: Рядок. Вказує носій (мікрофон, відео або камеру), захоплений входомtype="file"
.autoComplete
: Рядок. Вказує одну з можливих поведінок автозаповнення.autoFocus
: Логічний вираз. Якщоtrue
, React сфокусує елемент на монтуванні.dirname
: Рядок. Вказує ім'я поля форми для напрямку елемента.disabled
: Логічний вираз. Якщоtrue
, введення не буде інтерактивним і буде виглядати затемненим.children
:<input>
не приймає дітей.form
: Рядок. Вказує ідентифікаторid
елемента<form>
, до якого належить цей вхід. Якщо не вказано, це найближча батьківська форма.formAction
: Рядок. Перевизначає батьківський<form action>
дляtype="submit"
таtype="image"
.formEnctype
: Рядок. Перевизначає батьківський<form enctype>
дляtype="submit"
таtype="image"
.formMethod
: Рядок. Перевизначає батьківський<form method>
дляtype="submit"
таtype="image"
.formNoValidate
: Рядок. Перевизначає батьківський<form noValidate>
дляtype="submit"
таtype="image"
.formTarget
: Рядок. Перевизначає батьківський<form target>
дляtype="submit"
таtype="image"
.height
: Рядок. Вказує висоту зображення дляtype="image"
. .
list
: Рядок. Вказуєid
з<datalist>
з опціями автозаповнення.max
: Число. Вказує максимальне значення числових входів та входів часу даних.maxLength
: Число. Визначає максимальну довжину тексту та інших вхідних даних. .
min
: Число. Вказує мінімальне значення числових входів та входів часу даних.minLength
: Число. Визначає мінімальну довжину тексту та інших вхідних даних.multiple
: Булеве значення. Визначає, чи дозволено множинні значення для<type="file"
таtype="email"
.name
: Рядок. Вказує назву для цього входу, який було надіслано разом з формою.onChange
: Функція-обробникEvent
. Потрібна для контрольованих входів. Спрацьовує негайно, коли значення входу змінюється користувачем (наприклад, спрацьовує на кожне натискання клавіші). Поводиться як браузерinput
event.onChangeCapture
: ВерсіяonChange
, яка спрацьовує у фазі захоплення.onInput
: Функція-обробникEvent
. Спрацьовує негайно, коли користувач змінює значення. З історичних причин у React ідіоматичним є використанняonChange
, який працює аналогічно.onInputCapture
: ВерсіяonInput
, яка спрацьовує у фазі захоплення.onInvalid
: Функція-обробникEvent
. Спрацьовує, якщо вхідні дані не пройшли валідацію при надсиланні форми. На відміну від вбудованої подіїinvalid
, подія ReactonInvalid
bubbles.onInvalidCapture
: ВерсіяonInvalid
, яка спрацьовує у фазі захоплення.onSelect
: Функція-обробникEvent
. Спрацьовує після зміни виділення всередині<input>
. React розширює подіюonSelect
, щоб вона спрацьовувала також для порожнього виділення та при редагуванні (яке може вплинути на виділення).onSelectCapture
: ВерсіяonSelect
, яка спрацьовує у фазі захоплення.pattern
: Рядок. Вказує шаблон, якому має відповідатизначення
.placeholder
: Рядок. Відображається тьмяним кольором, якщо вхідне значення порожнє.readOnly
: Логічний вираз. Якщоtrue
, вхідні дані не можна редагувати користувачу.required
: Булеве значення. Якщоtrue
, значення має бути надано формі для відправки.size
: Число. Подібно до налаштування ширини, але одиниця виміру залежить від елемента керування.src
: Рядок. Вказує джерело зображення для входуtype="image"
. .
step
: Додатне число або рядок'any'
. Визначає відстань між допустимими значеннями.type
: Рядок. Один з типів входу.width
: Рядок. Вказує ширину зображення для вхідних данихtype="image"
.
Застереження
- Прапорці потрібно
встановити
(абоdefaultChecked
), а неvalue
(абоdefaultValue
). - Якщо текстове введення отримує рядковий
проп зі значенням
, він буде оброблений як контрольований. - Якщо прапорець або перемикач отримує відмічений булевий
проп
, він буде вважатися керованим. - Вхід не може бути одночасно контрольованим та неконтрольованим.
- Вхід не може перемикатися між контрольованим та неконтрольованим протягом свого життя.
- Кожному керованому входу потрібен обробник події
onChange
, який синхронно оновлює його опорне значення.
Використання
Відображення входів різних типів
Щоб відобразити вхідні дані, відрендеріть компонент<input>
. За замовчуванням це буде текстове введення. Ви можете передати type="checkbox"
для прапорця, type="radio"
для перемикача, або один з інших типів введення.
export default function MyForm() {
return (
<>
<label>
Text input: <input name="myInput" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" />
</label>
<hr />
<p>
Radio buttons:
<label>
<input type="radio" name="myRadio" value="option1" />
Option 1
</label>
<label>
<input type="radio" name="myRadio" value="option2" />
Option 2
</label>
<label>
<input type="radio" name="myRadio" value="option3" />
Option 3
</label>
</p>
</>
);
}
label { display: block; }
input { margin: 5px; }
Надання мітки для входу
Зазвичай ви розміщуєте кожну <input>
всередині тегу <label>
. Це повідомляє браузеру, що ця мітка пов'язана з цим входом. Коли користувач клацне на мітці, браузер автоматично сфокусує введення. Це також важливо для доступності: програма для зчитування з екрана озвучить підпис мітки, коли користувач сфокусує відповідне введення.
Якщо ви не можете вкласти <input>
у <label>
, об'єднайте їх, передавши однаковий ідентифікатор <input id>
та <label htmlFor>
. Щоб уникнути конфліктів між екземплярами одного компонента, згенеруйте такий ідентифікатор за допомогою useId
.
import { useId } from 'react';
export default function Form() {
const ageInputId = useId();
return (
<>
<label>
Your first name:
<input name="firstName" />
</label>
<hr />
<label htmlFor={ageInputId}>Your age:</label>
<input id={ageInputId} name="age" type="number" />
</>
);
}
input { margin: 5px; }
Надання початкового значення для входу
За бажанням ви можете вказати початкове значення для будь-якого входу. Для текстових введень передайте його у вигляді рядка defaultValue
. Прапорці та перемикачі повинні вказувати початкове значення за допомогою булевої функції defaultChecked
.
export default function MyForm() {
return (
<>
<label>
Text input: <input name="myInput" defaultValue="Some initial value" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
</label>
<hr />
<p>
Radio buttons:
<label>
<input type="radio" name="myRadio" value="option1" />
Option 1
</label>
<label>
<input
type="radio"
name="myRadio"
value="option2"
defaultChecked={true}
/>
Option 2
</label>
<label>
<input type="radio" name="myRadio" value="option3" />
Option 3
</label>
</p>
</>
);
}
label { display: block; }
input { margin: 5px; }
Зчитування вхідних значень під час надсилання форми
Додайте <form>
навколо ваших входів з <button type="submit">
всередині. Він викличе ваш обробник події <form onSubmit>
. За замовчуванням браузер відправить дані форми на поточну URL-адресу і оновить сторінку. Ви можете змінити цю поведінку, викликавши e.preventDefault()
. Прочитайте дані форми за допомогою new FormData(e.target)
.
export default function MyForm() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();
// Read the form data
const form = e.target;
const formData = new FormData(form);
// You can pass formData as a fetch body directly:
fetch('/some-api', { method: form.method, body: formData });
// Or you can work with it as a plain object:
const formJson = Object.fromEntries(formData.entries());
console.log(formJson);
}
return (
<form method="post" onSubmit={handleSubmit}>
<label>
Text input: <input name="myInput" defaultValue="Some initial value" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
</label>
<hr />
<p>
Radio buttons:
<label><input type="radio" name="myRadio" value="option1" /> Option 1</label>
<label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2</label>
<label><input type="radio" name="myRadio" value="option3" /> Option 3</label>
</p>
<hr />
<button type="reset">Reset form</button>
<button type="submit">Submit form</button>
</form>
);
}
label { display: block; }
input { margin: 5px; }
Дайте ім'я
кожному <input>
, наприклад <input name="firstName" defaultValue="Taylor" />
. Вказане вами name
буде використано як ключ у даних форми, наприклад { firstName: "Taylor" }
.
За замовчуванням, будь-який <button>
всередині <form>
надішле його. Це може бути несподівано! Якщо у вас є власний кастомний Button
React-компонент, розгляньте можливість повернення <button type="button">
замість <button>
. Тоді, для більшої ясності, використовуйте <button type="submit">
для кнопок, які мають надсилати форму.
Керування входом за допомогою змінної стану
Введення типу <input />
є неконтрольованим. Навіть якщо ви передаєте початкове значення типу <input defaultValue="Initial text" />
, ваш JSX лише вказує початкове значення. Він не контролює, яким має бути значення зараз.
Щоб відрендерити контрольоване введення, передайте йому проп value
(або перемикач
для чекбоксів та радіо). React змусить вхідні дані завжди мати значення , яке ви передали. Зазвичай ви робите це, оголошуючи змінну стану :
function Form() {
const [firstName, setFirstName] = useState(''); // Declare a state variable...
// ...
return (
<input
value={firstName} // ...force the input's value to match the state variable...
onChange={e => setFirstName(e.target.value)} // ... and update the state variable on any edits!
/>
);
}
Контрольоване введення має сенс, якщо вам все одно потрібен стан - наприклад, для повторного рендерингу інтерфейсу після кожного редагування:
function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
First name:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Your name is {firstName}.</p>}
...
Це також корисно, якщо ви хочете запропонувати декілька способів налаштування стану введення (наприклад, натисканням кнопки):
function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>
Значення , яке ви передаєте керованим компонентам, не повинно бути
невизначеним
або нульовим
. Якщо вам потрібно, щоб початкове значення було порожнім (як у випадку з полем firstName
нижче), ініціалізуйте вашу змінну стану порожнім рядком (''
).
import { useState } from 'react';
export default function Form() {
const [firstName, setFirstName] = useState('');
const [age, setAge] = useState('20');
const ageAsNumber = Number(age);
return (
<>
<label>
First name:
<input
value={firstName}
onChange={e => setFirstName(e.target.value)}
/>
</label>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>
</label>
{firstName !== '' &&
<p>Your name is {firstName}.</p>
}
{ageAsNumber > 0 &&
<p>Your age is {ageAsNumber}.</p>
}
</>
);
}
label { display: block; }
input { margin: 5px; }
p { font-weight: bold; }
Якщо ви передасте значення
без onChange
, ввід буде неможливим. Коли ви керуєте входом, передаючи йому деяке значення
, ви примушуєте його завжди мати значення, яке ви передали. Отже, якщо ви передасте змінну стану як значення
, але забудете синхронно оновити цю змінну стану під час обробника події onChange
, React повертатиме вхідні дані після кожного натискання клавіші до значення
, яке ви вказали.
Оптимізація повторного рендерингу на кожне натискання клавіші
Коли ви використовуєте контрольоване введення, ви встановлюєте стан на кожне натискання клавіші. Якщо компонент, який містить ваш стан, повторно рендерить велике дерево, це може бути повільним. Існує декілька способів оптимізувати продуктивність повторного рендерингу.
Наприклад, припустимо, що ви почнете з форми, яка повторно відображає весь вміст сторінки після кожного натискання клавіші:
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
Оскільки <PageContent />
не залежить від стану входу, ви можете перемістити стан входу у власний компонент:
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}
Це значно покращує продуктивність, оскільки тепер тільки SignupForm
рендериться повторно при кожному натисканні клавіші.
Якщо немає можливості уникнути повторного рендерингу (наприклад, якщо PageContent
залежить від значення пошукового входу), useDeferredValue
дозволяє зберегти керовані введення чуйним навіть під час великого повторного рендерингу.
Налагодження
Моє вікно введення тексту не оновлюється, коли я вводжу в нього текст
Якщо ви відрендерите введення зі значенням , але без
onChange
, ви побачите помилку у консолі:
// 🔴 Bug: controlled text input with no onChange handler
<input value={something} />
Ви надали проп значення
полю форми без обробника onChange
. Це призведе до того, що поле буде доступне лише для читання. Якщо поле має бути змінюваним, використовуйте defaultValue
. В іншому випадку задайте або onChange
, або readOnly
.
Як випливає з повідомлення про помилку, якщо ви хотіли вказати лише початкове значення, передайте defaultValue
замість цього:
// ✅ Good: uncontrolled input with an initial value
<input defaultValue={something} />
Якщо ви хочете керувати цим входом за допомогою змінної стану, вкажіть onChange
обробник:
// ✅ Good: controlled input with onChange
<input value={something} onChange={e => setSomething(e.target.value)} />
Якщо значення навмисно призначено лише для читання, додайте проп readOnly
для придушення помилки:
// ✅ Good: readonly controlled input without on change
<input value={something} readOnly={true} />
Мій прапорець не оновлюється, коли я натискаю на нього
Якщо ви відрендерите чекбокс з встановленим прапорцем
, але без onChange
, ви побачите помилку в консолі:
// 🔴 Bug: controlled checkbox with no onChange handler
<input type="checkbox" checked={something} />
Ви додали перевірений
проп до поля форми без обробника onChange
. Це призведе до того, що поле буде доступне тільки для читання. Якщо поле має бути змінюваним, використовуйте defaultChecked
. В іншому випадку задайте або onChange
, або readOnly
.
Як випливає з повідомлення про помилку, якщо ви хотіли вказати лише початкове значення, передайте defaultChecked
замість цього:
// ✅ Good: uncontrolled checkbox with an initial value
<input type="checkbox" defaultChecked={something} />
Якщо ви хочете керувати цим прапорцем за допомогою змінної стану, вкажіть onChange
обробник:
// ✅ Good: controlled checkbox with onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />
Для прапорців потрібно читати e.target.checked
, а не e.target.value
.
Якщо прапорець навмисно зроблено лише для читання, додайте проп readOnly
, щоб приховати помилку:
// ✅ Good: readonly controlled input without on change
<input type="checkbox" checked={something} readOnly={true} />
При кожному натисканні клавіші курсор введення перескакує на початок
Якщо ви керуєте входом, ви повинні оновити його змінну стану до значення входу з DOM під час onChange
.
Ви не можете оновити його на щось інше, ніж e.target.value
(або e.target.checked
для прапорців):
function handleChange(e) {
// 🔴 Bug: updating an input to something other than e.target.value
setFirstName(e.target.value.toUpperCase());
}
Ви також не можете оновлювати його асинхронно:
function handleChange(e) {
// 🔴 Bug: updating an input asynchronously
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
Щоб виправити код, синхронно оновіть його до e.target.value
:
function handleChange(e) {
// ✅ Updating a controlled input to e.target.value synchronously
setFirstName(e.target.value);
}
Якщо це не вирішить проблему, можливо, що при кожному натисканні клавіші дані вилучаються і додаються з DOM. Це може статися, якщо ви випадково скидаєте стан при кожному повторному рендерингу, наприклад, якщо вхід або один з його батьків завжди отримує інший атрибут ключа
, або якщо ви вкладаєте визначення функцій компонентів (що не підтримується і призводить до того, що "внутрішній" компонент завжди буде вважатися іншим деревом).
Я отримую помилку: "Компонент змінює неконтрольований вхід на контрольований"
Якщо ви надаєте компоненту значення
, воно має залишатися рядком протягом усього його життя.
Ви не можете передати спочатку value={undefined}
, а потім value="some string"
, оскільки React не знатиме, чи хочете ви зробити компонент некерованим чи керованим. Керований компонент завжди повинен отримувати рядок value
, а не null
або undefined
.
Якщо ваше значення
надходить з API або змінної стану, воно може бути ініціалізоване null
або undefined
. У такому випадку або спочатку встановіть його як порожній рядок (''
), або передайте value={someValue ?? ''}
, щоб переконатися, що value
є рядком.
Так само, якщо ви передаєте checked
до прапорця, переконайтеся, що він завжди є логічним.