內建瀏覽器元件 <textarea>
可讓您渲染多行文字輸入框。
<textarea />
參考
<textarea>
要顯示文字區域,請渲染內建瀏覽器元件 <textarea>
。
<textarea name="postContent" />
屬性 (Props)
<textarea>
支援所有常用元件屬性。
您可以透過傳遞 value
屬性來讓文字區域成為受控元件
value
:字串。控制文字區域內的文字。
當您傳遞 value
時,您也必須傳遞一個 onChange
事件處理函式來更新傳遞的值。
如果您的 <textarea>
是不受控的,您可以改為傳遞 defaultValue
屬性
defaultValue
:字串。指定文字區域的初始值。
以下 <textarea>
屬性與不受控和受控文字區域皆相關
autoComplete
:'on'
或'off'
。指定自動完成行為。autoFocus
:布林值。如果為true
,React 將在掛載時聚焦此元素。children
:<textarea>
不接受子元件。要設定初始值,請使用defaultValue
。cols
:數字。指定預設寬度,以平均字元寬度為單位。預設值為20
。disabled
:一個布林值。如果為true
,則輸入框將無法互動,並且會顯示為灰色。form
:一個字串。指定此輸入框所屬的<form>
的id
。如果省略,則為最接近的父表單。maxLength
:一個數字。指定文字的最大長度。minLength
:一個數字。指定文字的最小長度。name
:一個字串。指定此輸入框的名稱,該名稱會隨表單提交。onChange
:一個Event
事件處理器 函式。對於 受控文字區域 是必需的。當輸入框的值被使用者更改時(例如,每次按鍵都會觸發),會立即觸發。行為類似於瀏覽器的input
事件。onChangeCapture
:onChange
的一個版本,在 捕獲階段 觸發。onInput
:一個Event
事件處理器 函式。當值被使用者更改時立即觸發。由於歷史原因,在 React 中習慣使用功能類似的onChange
來代替。onInputCapture
:onInput
的一個版本,在 捕獲階段 觸發。onInvalid
:一個Event
事件處理器 函式。如果輸入在表單提交時驗證失敗,則觸發。與內建的invalid
事件不同,React 的onInvalid
事件會冒泡。onInvalidCapture
:onInvalid
的一個版本,在 捕獲階段 觸發。onSelect
:一個Event
事件處理器 函式。<textarea>
內的選取範圍更改後觸發。React 擴展了onSelect
事件,使其也能在選取範圍為空和編輯時觸發(這可能會影響選取範圍)。onSelectCapture
:onSelect
的一個版本,在 捕獲階段 觸發。placeholder
:一個字串。當文字區域值為空時,以灰色顯示。readOnly
:一個布林值。如果為true
,則文字區域不可由使用者編輯。required
:一個布林值。如果為true
,則表單提交時必須提供值。rows
:一個數字。指定預設高度,以平均字元高度為單位。預設值為2
。wrap
:'hard'
、'soft'
或'off'
。指定提交表單時應如何換行文字。
注意事項
- 不允許像
<textarea>something</textarea>
這樣傳遞子元素。使用defaultValue
來設定初始內容。 - 如果文字區域收到一個字串
value
屬性,它將被視為受控的。 - 文字區域不能同時是受控的和非受控的。
- 文字區域在其生命週期內不能在受控和非受控之間切換。
- 每個受控的文字區域都需要一個
onChange
事件處理程序,用於同步更新其背後的值。
用法
顯示文字區域
渲染 <textarea>
來顯示文字區域。您可以使用 rows
和 cols
屬性指定其預設大小,但預設情況下,使用者可以調整其大小。要禁用調整大小功能,您可以在 CSS 中指定 resize: none
。
export default function NewPost() { return ( <label> Write your post: <textarea name="postContent" rows={4} cols={40} /> </label> ); }
提供文字區域的標籤
通常,您會將每個 <textarea>
放在 <label>
標籤內。這會告訴瀏覽器此標籤與該文字區域相關聯。當使用者點擊標籤時,瀏覽器將聚焦文字區域。這對於無障礙功能也很重要:當使用者聚焦文字區域時,螢幕閱讀器會朗讀標籤標題。
如果您無法將 <textarea>
嵌套到 <label>
中,請將相同的 ID 傳遞給 <textarea id>
和 <label htmlFor>
來關聯它們。為了避免一個組件的實例之間發生衝突,請使用 useId
生成此類 ID。
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} /> </> ); }
export default function EditPost() { return ( <label> Edit your post: <textarea name="postContent" defaultValue="I really enjoyed biking yesterday!" rows={4} cols={40} /> </label> ); }
提交表單時讀取文字區域值
在您的 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> ); }
使用狀態變數控制文字區域
像 <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!
/>
);
}
如果您希望 UI 的某些部分在每次按鍵時都能重新渲染,這將很有用。
{ "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" }, "devDependencies": {} }
疑難排解
我的文字區域在我輸入時沒有更新 ...
如果您渲染一個帶有
如錯誤訊息所示,如果您只想 指定*初始*值,請改為傳遞 // ✅ Good: uncontrolled text area with an initial value
<textarea defaultValue={something} />
如果您想 使用狀態變數控制此文字區域,請指定一個
如果該值有意唯讀,請新增一個
我的文字區域插入符號在每次按鍵時都會跳到開頭 ...
如果您 控制文字區域,則必須在 您無法將其更新為
您也無法異步更新它
function handleChange(e) {
// 🔴 Bug: updating an input asynchronously
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
要修復您的程式碼,請將其同步更新為
如果這沒有解決問題,則可能是文字區域在每次按鍵時都會從 DOM 中移除並重新新增。如果您不小心在每次重新渲染時都 重置狀態,就會發生這種情況。例如,如果文字區域或其父元件之一始終收到不同的
我收到一個錯誤:「元件正在將非受控輸入變更為受控」
如果您提供 value
給元件,它在其生命週期內必須保持為字串。
您不能先傳遞 value={undefined}
,然後再傳遞 value="some string"
,因為 React 無法得知您希望元件是非受控還是受控。受控元件應該始終接收字串 value
,而不是 null
或 undefined
。
如果您的 value
來自 API 或狀態變數,它可能初始化為 null
或 undefined
。在這種情況下,請將其初始設定為空字串 (''
),或傳遞 value={someValue ?? ''}
以確保 value
是字串。