Component <input>
tích hợp sẵn của trình duyệt cho phép bạn render các loại input form khác nhau.
<input />
Tham khảo
<input>
Để hiển thị một input, render component <input>
tích hợp sẵn của trình duyệt.
<input name="myInput" />
Props
<input>
hỗ trợ tất cả các props phần tử thông thường.
formAction
: Một chuỗi hoặc một hàm. Ghi đè<form action>
của phần tử cha chotype="submit"
vàtype="image"
. Khi một URL được truyền choaction
, form sẽ hoạt động như một form HTML tiêu chuẩn. Khi một hàm được truyền choformAction
, hàm đó sẽ xử lý việc gửi form. Xem<form action>
.
Bạn có thể làm cho một input được kiểm soát bằng cách truyền một trong các props sau:
checked
: Một boolean. Đối với một input checkbox hoặc một radio button, kiểm soát xem nó có được chọn hay không.value
: Một chuỗi. Đối với một input văn bản, kiểm soát văn bản của nó. (Đối với một radio button, chỉ định dữ liệu form của nó.)
Khi bạn truyền một trong hai prop này, bạn cũng phải truyền một trình xử lý onChange
để cập nhật giá trị đã truyền.
Các props <input>
này chỉ liên quan đến các input không được kiểm soát:
defaultChecked
: Một boolean. Chỉ định giá trị ban đầu cho các inputtype="checkbox"
vàtype="radio"
.defaultValue
: Một chuỗi. Chỉ định giá trị ban đầu cho một input văn bản.
Các props <input>
này có liên quan đến cả input được kiểm soát và không được kiểm soát:
accept
: Một chuỗi. Chỉ định loại file nào được chấp nhận bởi một inputtype="file"
.alt
: Một chuỗi. Chỉ định văn bản thay thế hình ảnh cho một inputtype="image"
.capture
: Một chuỗi. Chỉ định phương tiện (microphone, video hoặc camera) được chụp bởi một inputtype="file"
.autoComplete
: Một chuỗi. Chỉ định một trong các hành vi autocomplete có thể.autoFocus
: Một boolean. Nếutrue
, React sẽ focus phần tử khi mount.dirname
: Một chuỗi. Chỉ định tên trường form cho hướng của phần tử.disabled
: Một boolean. Nếutrue
, input sẽ không tương tác được và sẽ xuất hiện màu xám.children
:<input>
không chấp nhận children.form
: Một chuỗi. Chỉ địnhid
của<form>
mà input này thuộc về. Nếu bị bỏ qua, nó là form cha gần nhất.formAction
: Một chuỗi. Ghi đè<form action>
của phần tử cha chotype="submit"
vàtype="image"
.formEnctype
: Một chuỗi. Ghi đè<form enctype>
của phần tử cha chotype="submit"
vàtype="image"
.formMethod
: Một chuỗi. Ghi đè<form method>
của phần tử cha chotype="submit"
vàtype="image"
.formNoValidate
: Một chuỗi. Ghi đè<form noValidate>
của phần tử cha chotype="submit"
vàtype="image"
.formTarget
: Một chuỗi. Ghi đè<form target>
của phần tử cha chotype="submit"
vàtype="image"
.height
: Một chuỗi. Chỉ định chiều cao hình ảnh chotype="image"
.list
: Một chuỗi. Chỉ địnhid
của<datalist>
với các tùy chọn autocomplete.max
: Một số. Chỉ định giá trị tối đa của các input số và ngày giờ.maxLength
: Một số. Chỉ định độ dài tối đa của văn bản và các input khác.min
: Một số. Chỉ định giá trị tối thiểu của các input số và ngày giờ.minLength
: Một số. Chỉ định độ dài tối thiểu của văn bản và các input khác.multiple
: Một boolean. Chỉ định xem nhiều giá trị có được phép cho<type="file"
vàtype="email"
hay không.name
: Một chuỗi. Chỉ định tên cho input này được gửi cùng với form.onChange
: Một hàmEvent
handler. Bắt buộc đối với các input được kiểm soát. Kích hoạt ngay lập tức khi giá trị của input bị thay đổi bởi người dùng (ví dụ: nó kích hoạt trên mỗi lần gõ phím). Hoạt động giống như sự kiệninput
của trình duyệt.onChangeCapture
: Một phiên bản củaonChange
kích hoạt trong giai đoạn capture.onInput
: Một hàmEvent
handler. Kích hoạt ngay lập tức khi giá trị bị thay đổi bởi người dùng. Vì lý do lịch sử, trong React, thành ngữ là sử dụngonChange
thay thế, hoạt động tương tự.onInputCapture
: Một phiên bản củaonInput
kích hoạt trong giai đoạn capture.onInvalid
: Một hàmEvent
handler. Kích hoạt nếu một input không vượt qua xác thực khi gửi form. Không giống như sự kiệninvalid
tích hợp, sự kiệnonInvalid
của React nổi bọt.onInvalidCapture
: Một phiên bản củaonInvalid
kích hoạt trong giai đoạn capture.onSelect
: Một hàmEvent
handler. Kích hoạt sau khi lựa chọn bên trong<input>
thay đổi. React mở rộng sự kiệnonSelect
để cũng kích hoạt cho lựa chọn trống và khi chỉnh sửa (có thể ảnh hưởng đến lựa chọn).onSelectCapture
: Một phiên bản củaonSelect
kích hoạt trong giai đoạn capture.pattern
: Một chuỗi. Chỉ định pattern màvalue
phải khớp.placeholder
: Một chuỗi. Được hiển thị bằng màu mờ khi giá trị input trống.readOnly
: Một boolean. Nếutrue
, input không thể chỉnh sửa được bởi người dùng.required
: Một boolean. Nếutrue
, giá trị phải được cung cấp để form được gửi.size
: Một số. Tương tự như cài đặt width, nhưng đơn vị phụ thuộc vào control.src
: Một chuỗi. Chỉ định nguồn hình ảnh cho một inputtype="image"
.step
: Một số dương hoặc một chuỗi'any'
. Chỉ định khoảng cách giữa các giá trị hợp lệ.type
: Một chuỗi. Một trong các loại input.width
: Một chuỗi. Chỉ định chiều rộng hình ảnh cho một inputtype="image"
.
Lưu ý
- Checkbox cần
checked
(hoặcdefaultChecked
), không phảivalue
(hoặcdefaultValue
). - Nếu một input văn bản nhận được một prop
value
kiểu chuỗi, nó sẽ được xử lý như được kiểm soát. - Nếu một checkbox hoặc một radio button nhận được một prop
checked
kiểu boolean, nó sẽ được xử lý như được kiểm soát. - Một input không thể vừa được kiểm soát vừa không được kiểm soát cùng một lúc.
- Một input không thể chuyển đổi giữa việc được kiểm soát hoặc không được kiểm soát trong suốt vòng đời của nó.
- Mọi input được kiểm soát cần một trình xử lý sự kiện
onChange
để đồng bộ cập nhật giá trị backing của nó.
Cách sử dụng
Hiển thị các input thuộc các loại khác nhau
Để hiển thị một input, render một component <input>
. Theo mặc định, nó sẽ là một input văn bản. Bạn có thể truyền type="checkbox"
cho một checkbox, type="radio"
cho một radio button, hoặc một trong các loại input khác.
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> </> ); }
Cung cấp một label cho một input
Thông thường, bạn sẽ đặt mọi <input>
bên trong một thẻ <label>
. Điều này cho trình duyệt biết rằng label này được liên kết với input đó. Khi người dùng nhấp vào label, trình duyệt sẽ tự động focus vào input. Nó cũng rất cần thiết cho khả năng truy cập: một trình đọc màn hình sẽ thông báo caption của label khi người dùng focus vào input được liên kết.
Nếu bạn không thể lồng <input>
vào một <label>
, hãy liên kết chúng bằng cách truyền cùng một ID cho <input id>
và <label htmlFor>
. Để tránh xung đột giữa nhiều instance của một component, hãy tạo một ID như vậy bằng 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" /> </> ); }
Cung cấp một giá trị ban đầu cho một input
Bạn có thể tùy chọn chỉ định giá trị ban đầu cho bất kỳ input nào. Truyền nó dưới dạng chuỗi defaultValue
cho các input văn bản. Checkbox và radio button nên chỉ định giá trị ban đầu bằng boolean defaultChecked
thay thế.
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> </> ); }
Đọc các giá trị input khi gửi form
Thêm một <form>
xung quanh các input của bạn với một <button type="submit">
bên trong. Nó sẽ gọi trình xử lý sự kiện <form onSubmit>
của bạn. Theo mặc định, trình duyệt sẽ gửi dữ liệu form đến URL hiện tại và làm mới trang. Bạn có thể ghi đè hành vi đó bằng cách gọi e.preventDefault()
. Đọc dữ liệu form bằng new FormData(e.target)
.
export default function MyForm() { function handleSubmit(e) { // Ngăn trình duyệt tải lại trang e.preventDefault(); // Đọc dữ liệu form const form = e.target; const formData = new FormData(form); // Bạn có thể truyền formData làm body fetch trực tiếp: fetch('/some-api', { method: form.method, body: formData }); // Hoặc bạn có thể làm việc với nó như một đối tượng thuần túy: 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> ); }
Kiểm soát một input bằng một biến trạng thái
Một input như <input />
là không được kiểm soát. Ngay cả khi bạn truyền một giá trị ban đầu như <input defaultValue="Initial text" />
, JSX của bạn chỉ chỉ định giá trị ban đầu. Nó không kiểm soát giá trị nên là gì ngay bây giờ.
Để render một input được kiểm soát, hãy truyền prop value
cho nó (hoặc checked
cho checkbox và radio). React sẽ buộc input luôn có value
mà bạn đã truyền. Thông thường, bạn sẽ làm điều này bằng cách khai báo một biến trạng thái:
function Form() {
const [firstName, setFirstName] = useState(''); // Khai báo một biến trạng thái...
// ...
return (
<input
value={firstName} // ...buộc giá trị của input khớp với biến trạng thái...
onChange={e => setFirstName(e.target.value)} // ...và cập nhật biến trạng thái trên mọi chỉnh sửa!
/>
);
}
Một input được kiểm soát có ý nghĩa nếu bạn cần trạng thái anyway—ví dụ: để re-render UI của bạn trên mọi chỉnh sửa:
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>}
...
Nó cũng hữu ích nếu bạn muốn cung cấp nhiều cách để điều chỉnh trạng thái input (ví dụ: bằng cách nhấp vào một button):
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>
value
bạn truyền cho các component được kiểm soát không được là undefined
hoặc null
. Nếu bạn cần giá trị ban đầu là trống (chẳng hạn như với trường firstName
bên dưới), hãy khởi tạo biến trạng thái của bạn thành một chuỗi trống (''
).
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> } </> ); }
Tối ưu hóa re-rendering trên mỗi lần gõ phím
Khi bạn sử dụng một input được kiểm soát, bạn đặt trạng thái trên mỗi lần gõ phím. Nếu component chứa trạng thái của bạn re-render một cây lớn, điều này có thể trở nên chậm. Có một vài cách bạn có thể tối ưu hóa hiệu suất re-rendering.
Ví dụ: giả sử bạn bắt đầu với một form re-render tất cả nội dung trang trên mỗi lần gõ phím:
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
Vì <PageContent />
không dựa vào trạng thái input, bạn có thể di chuyển trạng thái input vào component riêng của nó:
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}
Điều này cải thiện đáng kể hiệu suất vì bây giờ chỉ SignupForm
re-render trên mỗi lần gõ phím.
Nếu không có cách nào để tránh re-rendering (ví dụ: nếu PageContent
phụ thuộc vào giá trị của input tìm kiếm), useDeferredValue
cho phép bạn giữ cho input được kiểm soát phản hồi ngay cả ở giữa một re-render lớn.
Khắc phục sự cố
Input văn bản của tôi không cập nhật khi tôi nhập vào nó
Nếu bạn render một input với value
nhưng không có onChange
, bạn sẽ thấy một lỗi trong console:
// 🔴 Lỗi: input văn bản được kiểm soát không có trình xử lý onChange
<input value={something} />
value
cho một trường form mà không có trình xử lý onChange
. Điều này sẽ render một trường chỉ đọc. Nếu trường nên có thể thay đổi, hãy sử dụng defaultValue
. Nếu không, hãy đặt onChange
hoặc readOnly
.Như thông báo lỗi gợi ý, nếu bạn chỉ muốn chỉ định giá trị ban đầu, hãy truyền defaultValue
thay thế:
// ✅ Tốt: input không được kiểm soát với một giá trị ban đầu
<input defaultValue={something} />
Nếu bạn muốn kiểm soát input này bằng một biến trạng thái, hãy chỉ định một trình xử lý onChange
:
// ✅ Tốt: input được kiểm soát với onChange
<input value={something} onChange={e => setSomething(e.target.value)} />
Nếu giá trị cố ý chỉ đọc, hãy thêm một prop readOnly
để ngăn chặn lỗi:
// ✅ Tốt: input được kiểm soát chỉ đọc không có on change
<input value={something} readOnly={true} />
Checkbox của tôi không cập nhật khi tôi nhấp vào nó
Nếu bạn render một checkbox với checked
nhưng không có onChange
, bạn sẽ thấy một lỗi trong console:
// 🔴 Lỗi: checkbox được kiểm soát không có trình xử lý onChange
<input type="checkbox" checked={something} />
checked
cho một trường form mà không có trình xử lý onChange
. Điều này sẽ render một trường chỉ đọc. Nếu trường nên có thể thay đổi, hãy sử dụng defaultChecked
. Nếu không, hãy đặt onChange
hoặc readOnly
.Như thông báo lỗi gợi ý, nếu bạn chỉ muốn chỉ định giá trị ban đầu, hãy truyền defaultChecked
thay thế:
// ✅ Tốt: checkbox không được kiểm soát với một giá trị ban đầu
<input type="checkbox" defaultChecked={something} />
Nếu bạn muốn kiểm soát checkbox này bằng một biến trạng thái, hãy chỉ định một trình xử lý onChange
:
// ✅ Tốt: checkbox được kiểm soát với onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />
Nếu checkbox cố ý chỉ đọc, hãy thêm một prop readOnly
để ngăn chặn lỗi:
// ✅ Tốt: input được kiểm soát chỉ đọc không có on change
<input type="checkbox" checked={something} readOnly={true} />
Caret input của tôi nhảy về đầu trên mỗi lần gõ phím
Nếu bạn kiểm soát một input, bạn phải cập nhật biến trạng thái của nó thành giá trị của input từ DOM trong onChange
.
Bạn không thể cập nhật nó thành một thứ khác ngoài e.target.value
(hoặc e.target.checked
cho checkbox):
function handleChange(e) {
// 🔴 Lỗi: cập nhật một input thành một thứ khác ngoài e.target.value
setFirstName(e.target.value.toUpperCase());
}
Bạn cũng không thể cập nhật nó một cách không đồng bộ:
function handleChange(e) {
// 🔴 Lỗi: cập nhật một input một cách không đồng bộ
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
Để sửa mã của bạn, hãy cập nhật nó một cách đồng bộ thành e.target.value
:
function handleChange(e) {
// ✅ Cập nhật một input được kiểm soát thành e.target.value một cách đồng bộ
setFirstName(e.target.value);
}
Nếu điều này không khắc phục được sự cố, có thể input bị xóa và thêm lại từ DOM trên mỗi lần gõ phím. Điều này có thể xảy ra nếu bạn vô tình đặt lại trạng thái trên mỗi lần re-render, ví dụ: nếu input hoặc một trong các phần tử cha của nó luôn nhận một thuộc tính key
khác nhau, hoặc nếu bạn lồng các định nghĩa hàm component (điều này không được hỗ trợ và khiến component “bên trong” luôn được coi là một cây khác).
Tôi đang gặp lỗi: “Một component đang thay đổi một input không được kiểm soát thành được kiểm soát”
Nếu bạn cung cấp một value
cho component, nó phải duy trì là một chuỗi trong suốt vòng đời của nó.
Bạn không thể truyền value={undefined}
trước và sau đó truyền value="some string"
vì React sẽ không biết bạn muốn component không được kiểm soát hay được kiểm soát. Một component được kiểm soát phải luôn nhận một value
kiểu chuỗi, không phải null
hoặc undefined
.
Nếu value
của bạn đến từ một API hoặc một biến trạng thái, nó có thể được khởi tạo thành null
hoặc undefined
. Trong trường hợp đó, hãy đặt nó thành một chuỗi trống (''
) ban đầu, hoặc truyền value={someValue ?? ''}
để đảm bảo value
là một chuỗi.
Tương tự, nếu bạn truyền checked
cho một checkbox, hãy đảm bảo nó luôn là một boolean.