<textarea>
Вбудований компонент браузера <textarea>
дозволяє відображати багаторядкове введення тексту.
<textarea />
Довідник
<textarea>
Щоб відобразити текстову область, викличте компонент вбудованого браузера <textarea>
.
<textarea name="postContent" />
Дивіться більше прикладів нижче.
Пропси
<textarea>
підтримує всі пропси спільних елементів.
Ви можете зробити текстову область керованою, передавши значення
prop:
value
: Рядок. Керує текстом всередині текстової області.
При передачі значення
ви також повинні передати обробник onChange
, який оновлює передане значення.
Якщо ваш <textarea>
є неконтрольованим, ви можете передати замість нього проп defaultValue
:
defaultValue
: Рядок. Вказує початкове значення для текстової області.
Ці <textarea>
пропси стосуються як неконтрольованих, так і контрольованих текстових областей:
autoComplete
: Або'on'
, або'off'
. Вказує поведінку автозаповнення.autoFocus
: Булевий вираз. Якщоtrue
, React сфокусує елемент на mount. .
children
:<textarea>
не приймає дітей. Для встановлення початкового значення використовуйтеdefaultValue
. .
cols
: Число. Вказує ширину за замовчуванням у середній ширині символів. За замовчуванням20
. .
disabled
: Булевий вираз. Якщоtrue
, введення не буде інтерактивним і буде виглядати затемненим.form
: Рядок. Вказуєid
елемента<form>
, до якого належить цей вхід. Якщо не вказано, це найближча батьківська форма.maxLength
: Число. Вказує максимальну довжину тексту. .
minLength
: Число. Вказує мінімальну довжину тексту.name
: Рядок. Вказує назву для цього входу, який було надіслано разом з формою.onChange
: Функція-обробникEvent
. Потрібна для контрольованих текстових областей. Спрацьовує негайно, коли користувач змінює значення входу (наприклад, спрацьовує при кожному натисканні клавіші). Поводиться як браузерinput
event.onChangeCapture
: ВерсіяonChange
, яка спрацьовує у фазі захоплення.onInput
: Функція-обробникEvent
. функція. Спрацьовує негайно, коли значення змінюється користувачем. З історичних причин у React ідіоматично використовуватиonChange
, яка працює аналогічно.onInputCapture
: ВерсіяonInput
, яка спрацьовує у фазі захоплення.onInvalid
: Функція-обробникEvent
. Спрацьовує, якщо вхідні дані не пройшли валідацію при надсиланні форми. На відміну від вбудованої подіїinvalid
, подія ReactonInvalid
bubbles.onInvalidCapture
: ВерсіяonInvalid
, яка спрацьовує у фазі захоплення.onSelect
: Функція-обробникEvent
. Спрацьовує після зміни виділення всередині<textarea>
. React розширює подіюonSelect
, щоб вона спрацьовувала також для порожнього виділення та при редагуванні (яке може вплинути на виділення).onSelectCapture
: ВерсіяonSelect
, яка спрацьовує у фазі захоплення.placeholder
: Рядок. Відображається тьмяним кольором, якщо значення текстової області порожнє.readOnly
: Логічне значення. Якщоtrue
, текстова область недоступна для редагування користувачем.required
: Булеве значення. Якщоtrue
, значення має бути надано формі для відправки.rows
: Число. Вказує висоту за замовчуванням у середніх висотах символів. За замовчуванням2
.wrap
: Або'hard'
,'soft'
, або'off'
. Вказує, як слід обгортати текст при надсиланні форми.
Застереження
- Не дозволяється пропускати таких дітей, як
<textarea>something</textarea>
. ВикористовуйтеdefaultValue
для початкового вмісту. - Якщо текстова область отримує проп
значення
, вона буде оброблена як керована. - Текстова область не може бути одночасно контрольованою та неконтрольованою.
- Текстова область не може перемикатися між контрольованою та неконтрольованою протягом свого життя.
- Кожна контрольована текстова область потребує обробник подій
onChange
, який синхронно оновлює її опорне значення.
Використання
Відображення текстової області
Зобразити <textarea>
для відображення текстової області. За допомогою атрибутів rows
та cols
можна вказати її розмір за замовчуванням, але за замовчуванням користувач матиме змогу змінити її розмір. Щоб вимкнути зміну розміру, ви можете вказати resize: none
в CSS.
export default function NewPost() {
return (
<label>
Write your post:
<textarea name="postContent" rows={4} cols={40} />
</label>
);
}
input { margin-left: 5px; }
textarea { margin-top: 10px; }
label { margin: 10px; }
label, textarea { display: block; }
Надання мітки для текстової області
Зазвичай, ви розміщуєте кожну <textarea>
всередині тегу <label>
. Це повідомляє браузеру, що ця мітка пов'язана з цією текстовою областю. Коли користувач клацне на мітці, браузер сфокусує текстову область. Це також важливо для доступності: програма для читання з екрана озвучить підпис мітки, коли користувач сфокусує текстову область.
Якщо ви не можете вкласти <textarea>
у <label>
, об'єднайте їх, передавши однаковий ідентифікатор <textarea id>
та <label htmlFor>
. Щоб уникнути конфліктів між екземплярами одного компонента, згенеруйте такий ідентифікатор за допомогою useId
.
import { useId } from 'react';
export default function Form() {
const postTextAreaId = useId();
return (
<>
<label htmlFor={postTextAreaId}>
Write your post:
</label>
<textarea
id={postTextAreaId}
name="postContent"
rows={4}
cols={40}
/>
</>
);
}
input { margin: 5px; }
Надання початкового значення для текстової області
За бажанням ви можете вказати початкове значення для текстової області. Передайте його як рядок defaultValue
.
export default function EditPost() {
return (
<label>
Edit your post:
<textarea
name="postContent"
defaultValue="I really enjoyed biking yesterday!"
rows={4}
cols={40}
/>
</label>
);
}
input { margin-left: 5px; }
textarea { margin-top: 10px; }
label { margin: 10px; }
label, textarea { display: block; }
На відміну від HTML, передача початкового тексту на зразок <textarea>Some content</textarea>
не підтримується.
Зчитування значення текстової області під час надсилання форми
Додайте <form>
навколо вашої текстової області з <button type="submit">
всередині. Він викличе ваш обробник події <form onSubmit>
. За замовчуванням браузер відправить дані форми на поточну URL-адресу і оновить сторінку. Ви можете змінити цю поведінку, викликавши e.preventDefault()
. Прочитайте дані форми за допомогою new FormData(e.target)
.
export default function EditPost() {
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>
Post title: <input name="postTitle" defaultValue="Biking" />
</label>
<label>
Edit your post:
<textarea
name="postContent"
defaultValue="I really enjoyed biking yesterday!"
rows={4}
cols={40}
/>
</label>
<hr />
<button type="reset">Reset edits</button>
<button type="submit">Save post</button>
</form>
);
}
label { display: block; }
input { margin: 5px; }
Дайте ім'я
вашому <textarea>
, наприклад <textarea name="postContent" />
. Вказане вами name
буде використано як ключ у даних форми, наприклад { postContent: "Your post" }
.
За замовчуванням, будь-який <button>
всередині <form>
надішле його. Це може бути несподівано! Якщо у вас є власний кастомний Button
React-компонент, розгляньте можливість повернення <button type="button">
замість <button>
. Тоді, для більшої ясності, використовуйте <button type="submit">
для кнопок, які мають надсилати форму.
Керування текстовою областю за допомогою змінної стану
Текстова область на зразок <textarea />
є неконтрольованою. Навіть якщо ви передасте початкове значення як <textarea defaultValue="Initial text" />
, ваш JSX вказує лише початкове значення, а не значення у даний момент.
Щоб відрендерити контрольовану текстову область, передайте їй проп value
. React змусить текстову область завжди мати передане вами значення value
. Зазвичай ви керуєте текстовою областю, оголошуючи змінну стану :
function NewPost() {
const [postContent, setPostContent] = useState(''); // Declare a state variable...
// ...
return (
<textarea
value={postContent} // ...force the input's value to match the state variable...
onChange={e => setPostContent(e.target.value)} // ... and update the state variable on any edits!
/>
);
}
Це корисно, якщо ви хочете повторно відрендерити якусь частину інтерфейсу у відповідь на кожне натискання клавіші.
import { useState } from 'react';
import MarkdownPreview from './MarkdownPreview.js';
export default function MarkdownEditor() {
const [postContent, setPostContent] = useState('_Hello,_ **Markdown**!');
return (
<>
<label>
Enter some markdown:
<textarea
value={postContent}
onChange={e => setPostContent(e.target.value)}
/>
</label>
<hr />
<MarkdownPreview markdown={postContent} />
</>
);
}
import { Remarkable } from 'remarkable';
const md = new Remarkable();
export default function MarkdownPreview({ markdown }) {
const renderedHTML = md.render(markdown);
return <div dangerouslySetInnerHTML={{__html: renderedHTML}} />;
}
{
"dependencies": {
"react": "latest",
"react-dom": "latest",
"react-scripts": "latest",
"remarkable": "2.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
textarea { display: block; margin-top: 5px; margin-bottom: 10px; }
Якщо ви передасте значення
без onChange
, ввести текст у текстову область буде неможливо. Коли ви керуєте текстовим полем, передаючи йому деяке значення
, ви примушуєте його завжди мати значення, яке ви передали. Отже, якщо ви передасте змінну стану як значення
, але забудете синхронно оновити цю змінну стану під час обробника події onChange
, React повертатиме текстову область після кожного натискання клавіші до вказаного вами значення
.
Налагодження
Моя текстова область не оновлюється, коли я вводжу в неї текст
Якщо ви відрендерите текстову область із значенням
, але без onChange
, ви побачите помилку у консолі:
// 🔴 Bug: controlled text area with no onChange handler
<textarea value={something} />
Ви надали проп значення
полю форми без обробника onChange
. Це призведе до того, що поле буде доступне лише для читання. Якщо поле має бути змінюваним, використовуйте defaultValue
. В іншому випадку задайте або onChange
, або readOnly
.
Як випливає з повідомлення про помилку, якщо ви хотіли вказати лише початкове значення, передайте defaultValue
замість цього:
// ✅ Good: uncontrolled text area with an initial value
<textarea defaultValue={something} />
Якщо ви хочете керувати цією текстовою областю за допомогою змінної стану, вкажіть onChange
обробник:
// ✅ Good: controlled text area with onChange
<textarea value={something} onChange={e => setSomething(e.target.value)} />
Якщо значення навмисно призначено лише для читання, додайте проп readOnly
для придушення помилки:
// ✅ Good: readonly controlled text area without on change
<textarea value={something} readOnly={true} />
Мій маркер текстової області перескакує на початок після кожного натискання клавіші
Якщо ви контролюєте текстову область, ви повинні оновити її змінну стану до значення текстової області з DOM протягом onChange
.
Ви не можете оновити його на щось інше, ніж e.target.value
:
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 при кожному натисканні клавіші. Це може статися, якщо ви випадково скидаєте стан при кожному повторному рендерингу. Наприклад, це може статися, якщо текстова область або один з її батьків завжди отримує інший атрибут ключа
, або якщо ви вкладаєте визначення компонентів (що не дозволено в React і призводить до того, що "внутрішній" компонент перемонтується при кожному рендерингу).
Я отримую помилку: "Компонент змінює неконтрольований вхід на контрольований"
Якщо ви надаєте компоненту значення
, воно має залишатися рядком протягом усього його життя.
Ви не можете передати спочатку value={undefined}
, а потім value="some string"
, оскільки React не знатиме, чи хочете ви зробити компонент некерованим чи керованим. Керований компонент завжди повинен отримувати рядок value
, а не null
або undefined
.
Якщо ваше значення
надходить з API або змінної стану, воно може бути ініціалізоване null
або undefined
. У такому випадку або спочатку встановіть його як порожній рядок (''
), або передайте value={someValue ?? ''}
, щоб переконатися, що value
є рядком.